Préambule
=========
"Seventy-five thousand generations ago, our ancestors set this program
in motion," the second man said, "and in all that time we will be the
first to hear the computer speak."
"An awesome prospect, Phouchg," agreed the first man, and Arthur
suddenly realized that he was watching a recording with subtitles.
"We are the ones who will hear," said Phouchg, "the answer to the
great question of Life ...!"
"The Universe ...!" said Loonquawl.
"And Everything ...!"
"Shhh," said Loonquawl with a slight gesture, "I think Deep Thought is
preparing to speak!"
There was a moment's expectant pause whilst panels slowly came to life
on the front of the console. Lights flashed on and off experimentally
and settled down into a businesslike pattern. A soft low hum came
from the communication channel.
"Good morning," said Deep Thought at last.
"Er ... Good morning, O Deep Thought," said Loonquawl nervously, "do
you have ... er, that is ..."
"An answer for you?" interrupted Deep Thought majestically. "Yes. I
have."
The two men shivered with expectancy. Their waiting had not been in
vain.
"There really is one?" breathed Phouchg.
"There really is one," confirmed Deep Thought.
"To Everything? To the great Question of Life, the Universe and
Everything?"
"Yes."
Both of the men had been trained for this moment, their lives had been
a preparation for it, they had been selected at birth as those who
would witness the answer, but even so they found themselves gasping
and squirming like excited children.
"And you're ready to give it to us?" urged Loonquawl.
"I am."
"Now?"
"Now," said Deep Thought.
They both licked their dry lips.
"Though I don't think," added Deep Thought, "that you're going to like
it."
Indications administratives
===========================
- La date de rendu du projet n'est pas encore totalement fixée, elle se
situera au alentour des partiels du mois d'avril. La date exacte vous
sera communiquée très prochainement.
- Le projet doit être réalisé par groupes de 6 personnes exactement,
dont les noms et les logins doivent figurer dans le fichier AUTHORS,
et indiqués par mail à acu@epita.fr en utilisant un sujet de la forme:
[42SH-INSCRIPTIONS] login1:login2:login3:login4:login5:login6
- Le premier login est considéré être le "chef de groupe" : c'est le
compte de ce login, et uniquement de celui-ci, qui doit être utilisé
pour le rendu. Les inscriptions aux soutenances doivent également
être faites par cette personne.
- L'évaluation aura lieu par groupe. Tout le groupe aura la même note,
sauf cas exceptionnel.
- Le newsgroup officiel pour ce projet est "epita.cours.c-unix.42sh".
Les responsables du projet sont les Assistants C/Unix. Les
changements ou précisions apportées au sujet suite a une news seront
repercutés dans la FAQ du sujet.
Modalités de rendu
=================
- Vous devez stocker vos sources dans le répertoire
~/c/rendu/proj/42sh en les protégeant contre l'accès par d'autres
utilisateurs (droits en 600 ou 700).
- Les sources du projet doivent être conformes au CSS EPITA, notamment
concernant les fichiers AUTHORS et Makefile.
- La règle all du fichier Makefile doit provoquer la création de
l'executable demandé : "42sh".
- Le rendu doit être effectué en utilisant le script de rendu des ACUs
~acu/mbin/rendu.sh proj 42sh
Contraintes techniques
======================
- Vous devez coder ce projet en C.
- Vous avez désormais le droit d'utiliser les fonctions de la
bibliothèque standard. Ne réinventez donc pas la roue. Toutefois les
fonctions suivantes et apparentées de gestion de méta-caractères
sont strictement interdites : glob(3), regexec(3), fnmatch(3). Si
vous avez un doute, posez la question dans les news.
- L'utilisation de la fonction readline(3) (de la bibliothèque GNU du
même nom) est interdite.
- Les sources doivent être conformes au CSS.
- Votre projet doit compiler et fonctionner identiquement sur les
trois architectures de l'école auxquelles vous avez couramment accès
(i386-unknown-netbsdelf1.6, alphaev56-dec-osf4.0d et
sparc-sun-solaris2.8).
- Vous êtes autorisés à utiliser gcc sur les trois architectures,
cependant les options de compilations sont fixées et obligatoires.
Votre projet DOIT être compilé avec les options suivantes :
"-Wall -pedantic -ansi -Werror"
Conseils techniques
===================
Vous êtes invités et encouragés à utiliser les outils suivants :
- CVS ou tout autre système de gestion de sources pour un groupe de
développeurs.
- les Autotools
Description du projet
=====================
Ce projet consiste à réaliser un interpréteur de commandes Unix (ou
shell) de type Bourne. Les buts sont multiples.
Le but premier est de consolider vos connaissances dans le domaine du
C/Unix durant toute la durée de la P2. Il est impératif que vous
n'oubliiez pas cette partie de votre apprentissage. Pour cette raison
des évaluations régulières auront lieu afin de ne pas vous laisser la
possibilité de les oublier.
Nous désirons également vous mettre face à la rigueur que vous
rencontrerez dans votre vie d'entreprise. Les critères de notation
seront donc très stricts, et vous aurez affaire à une moulinette. Il
vous est donc demandé de lire très attentivement le sujet et de vous y
tenir.
Enfin, nous avons remarqué que la bonne utilisation d'un shell faisait
défaut à beaucoup d'entre vous. Ce sujet est la dernière occasion et
aussi la meilleure d'inverser la tendance. Nous attendons donc de vous
que vous vous intéressiez à toutes les parties du sujet, que vous
décidiez de les implémenter ou non.
La ligne directrice que vous devez suivre tout au long du
développement du projet est la _stabilité_. Ne visez pas trop haut, ne
cherchez pas à implémenter des fonctionnalités étendues si vous n'êtes
pas sûrs du fonctionnement de celles de base.
En effet, il n'existe pas à nos yeux d'"à peu près" dans ce
domaine. Cela fonctionne, ou non... La notation va dans ce sens.
Évidemment votre programme doit être à tout épreuve, toutes les
erreurs doivent être contrôlées, ce qui implique l'IMPOSSIBILITÉ de
l'émission de SIGSEGV ou autre. Tout manquement à ce principe sera
sévèrement pénalisé. Inspirez vous des lectures qui vous sont
proposées en fin de sujet, car nous le ferons également...
Placez-vous dans une optique extrême : vous devez pouvoir rapidement
utiliser votre shell comme seul shell, ce qui vous oblige à changer
votre définition d'un programme à toute épreuve...
Une autre partie intéressante du sujet est la gestion de la
grammaire. Ce projet est sûrement le dernier où il vous sera demandé
d'écrire un analyseur lexical et syntaxique sans utiliser d'outils
externes. Et contrairement aux sujets précédents qui vous le
demandaient, l'exercice est cette fois beaucoup plus difficile.
Les "bricolages" ne seront donc pas tolérés, il est impératif que vous
ayez mis au clair la grammaire sur laquelle vous travaillez.
Nous vous demandons de séparer très clairement dans votre code le
« scanner » et le « parser ». Le flux de tokens généré par le premier
doit être clairement apparent, de même que son traitement par le
second.
La grammaire à utiliser est présentée dans le document donné en
deuxième lecture. Il est évident que vous ne devez gérer que la partie
de la grammaire qui correspond aux parties que vous implémentez. Si
des cas ambigus ou indéfinis vous apparaissent, n'hésitez pas à
demander un éclaircissement dans les news.
Nous insistons sur le fait qu'il n'est PAS question pour vous de gérer
la grammaire complète. A vous d'isoler les parties importantes de
celle-ci en fonction des parties que vous choisissez d'implémenter.
Évaluation
==========
Le projet est découpé en deux parties, la partie obligatoire et la
partie « rémunérée ». Elles seront toutes les deux évaluées par des
moulinettes.
La partie obligatoire ne rapporte qu'un point symbolique. Et surtout,
le reste de votre shell ne sera pas évalué si cette partie n'est pas
validée.
La moulinette de la partie obligatoire réalise un grand nombre de
tests, on considèrera que la partie est validée si au moins 98% des
tests réussissent. Les méthodes et critères de tests sont détaillés
plus loin.
Si cette partie est validée, il vous sera ensuite demandé de lister
les parties rémunérées que vous savez avoir implémentées ; un jeu de
tests sera ensuite chargé de les évaluer séparément. De même, une
"partie" est considérée valide, si 98% des tests passent, sinon il ne
sera attribué aucun point à l'ensemble de la partie.
Certaines parties ne pourront cependant pas être évaluées de cette
façon, c'est le cas du "readline" par exemple. Le bon fonctionnement
sera alors déterminé par le souteneur lui même.
Les boni sont fixes, il y a assez matière à travailler avec l'ensemble
des parties rémunérées proposées. Si vous pensez vraiment avoir tout
implémenté, venez nous en parler...
La moulinette de la partie obligatoire pourra être passée à votre
demande lors des soutenances intermédiaires. Les résultats précis ne
vous seront pas communiqués : vous aurez juste des indices sur les
points à corriger.
Étant donnée l'importance capitale de la partie obligatoire sur la
note finale, vous êtes plus qu'invités à la travailler rigoureusement
pour les soutenances intermédiaires.
Toutefois, les soutenances intermédiaires ont surtout pour but de
présenter l'évolution de votre projet. Un certain nombre de
démonstrations sont attendues visant à vous attribuer un point de
bonus ou de malus, qui sera reporté sur la note finale (sous réserve
que la partie obligatoire fonctionne). Ce qui est exactement attendu
est décrit dans une autre partie du sujet.
Partie obligatoire
==================
Le document se trouvant en première lecture "XSI Shell Command
Language" définit de façon exacte et exhaustive le comportement que
nous attendons de votre shell. Le sujet se borne donc à en isoler
certaines parties pour distinguer les différents niveaux de
difficultés.
Votre shell DOIT donc respecter le comportement que décrit le
document. Bash 2.05, disponible a l'école, respecte les points de
cette norme qui sont demandés dans le sujet.
N'hésitez pas à tester les commandes avec bash. N'en copiez cependant
pas les cas indéfinis, le fonctionnement dans ce genre de cas, non
précisés par la norme "XSI Shell Command Language", est laissé à votre
discrétion.
1) Entrée utilisateur
---------------------
Lorsqu'on lance le programme sans arguments et que l'entrée est un
tty, celui-ci doit présenter une invite (prompt) à l'utilisateur et
l'autoriser à saisir des commandes sur l'entrée standard.
L'invite par défaut est "42$ ".
Par exemple :
$ ./42sh
42$ cd
42$ #ceci est un commentaire.
42$ find . | xargs md5 > .hash
42$ ls -l .ha*
-rw------- 1 poss_r wheel 3706 Jan 6 01:20 .hash
42$ exit
$
Lorsque l'on lance le programme sans arguments et que l'entrée n'est
pas un tty, celui-ci doit lire ses commandes sur l'entrée standard et
quitter.
Par exemple :
$ ls
rien tata titi toto
$ echo "ls | grep -v ti | wc -l > /tmp/file && cat /tmp/file" | ./42sh
3
$
Lorsqu'on lance le programme avec un nom de fichier en argument,
celui-ci doit exécuter les commandes contenues dans le fichier et
quitter.
Par exemple :
$ cat my.sh
cd
find . | xargs md5 > .hash
$ ./42sh my.sh
$ ls -l .ha*
-rw------- 1 rn staff 3706 Jan 6 01:20 .hash
$
ou
$ cat my.sh
#! /u/staff/rn/c/rendu/proj/42sh/42sh
cd
find . | xargs md5 > .hash
$ chmod +x my.sh && ./my.sh
$ ls -l .ha*
-rw------- 1 rn staff 3706 Jan 6 01:20 .hash
$
Lorsque l'on lance le programme avec l'option -c "string", celui-ci
doit exécuter les commandes contenues dans "string" et quitter.
Par exemple :
$ ls -al
total 3
drwx--x--x 2 max wheel 512 Jan 21 17:36 .
drwxrwxrwt 8 root wheel 512 Jan 21 17:37 ..
-rw------- 1 max wheel 3 Jan 21 17:36 file
-rw------- 1 max wheel 0 Jan 21 16:53 rien
-rw------- 1 max wheel 0 Jan 21 16:51 tata
-rw------- 1 max wheel 0 Jan 21 16:51 titi
-rw------- 1 max wheel 0 Jan 21 16:51 toto
$ ./42sh -c 'echo t[aio]* | xargs ls -al | sed s/max/rn/'
-rw------- 1 rn wheel 0 Jan 21 16:51 tata
-rw------- 1 rn wheel 0 Jan 21 16:51 titi
-rw------- 1 rn wheel 0 Jan 21 16:51 toto
$
2) Redirections
---------------
Le shell doit permettre de rediriger l'entrée, la sortie standard et
la sortie d'erreur de n'importe quelle commande depuis ou vers un
fichier.
Le format global pour les redirections est celui-ci :
[n]operateur-de-redirection fichier
n étant le numéro du descripteur de fichier à rediriger.
Les opérateurs de redirection que vous devez implémenter pour cette
partie sont : '>' '>>' et '<'.
Les cas « ambigus » de redirection sont dépendants de votre
implémentation, néanmoins rappelez-vous que votre programme ne doit
pas générer d'erreur qu'il ne sait pas contrôler.
Par exemple :
42$ > /tmp/out cat < /etc/resolv.conf
42$ < /etc/passwd cat -n | grep -v root | grep sbin >> /tmp/out 2> /dev/null
42$ < /tmp/out cat
;
; BIND data file
; Created by NetBSD sysinst on Sun Aug 11 12:36:18 2002
;
nameserver 10.42.6.6
search epita.fr
4 daemon:*:1:31:The devil himself:/:/sbin/nologin
5 operator:*:2:5:System &:/usr/guest/operator:/sbin/nologin
6 bin:*:3:7:Binaries Commands and Source:/:/sbin/nologin
7 news:*:6:8:Network News:/var/spool/news:/sbin/nologin
8 games:*:7:13:& pseudo-user:/usr/games:/sbin/nologin
9 postfix:*:12:12:& pseudo-user:/var/spool/postfix:/sbin/nologin
14 nobody:*:32767:39:Unprivileged user:/nonexistent:/sbin/nologin
42$
3) Exécution de commandes
-------------------------
Toutes les fonctions exec*(3) sont autorisées. Seule la gestion
avancée du PATH (partie rémunérée) impose des restrictions à ce sujet.
Vous devez gérer les opérateurs suivant au sens où ils sont définis
dans le document de référence :
- ';'
- '&'
- '|'
- '||'
- '&&'
Et le '!' en début de pipeline.
4) Quoting
----------
Vous devez gérer les différents niveaux d'inhibition (« quoting »)
présentés dans le document de référence :
- '\'
- '"'
- '''
Les gérer strictement dans la partie obligatoire ne représente pas un
travail très difficile, cependant l'implémentation des parties
rémunérées vous obligera à gérer des cas supplémentaires.
5) Expansion des chemins
------------------------
Votre shell doit procéder automatiquement à certaines substitutions
dans les mots dès que certains caractères s'y trouvent.
A ce niveau de sujet, les seules expansion qui vous sont demandées sont :
- '*'
- '?'
- '[]', avec la possibilité d'utiliser le '-' dans les '[]'
6) Builtins simples
-------------------
Votre shell doit gérer des commandes intégrées qui ne provoquent pas
l'exécution d'un programme.
Vous devez gérer au moins les commandes intégrées suivantes :
- cd : change de répertoire courant
"cd" doit fonctionner
"cd -" doit fonctionner
- exit [n] : termine le shell en retournant le code d'erreur n
- echo : affiche ses arguments.
"echo -n" doit fonctionner
"echo -e" doit fonctionner
"echo -E" doit fonctionner (par defaut xpg_echo est desactivée)
Les commandes intégrées doivent évidemment se comporter comme les
autres au moins vis-à-vis du traitement des arguments et de l'effet
des redirections.
7) Respect de la grammaire
--------------------------
Hormis les parties indispensables permettant de gérer les cas décrits
ci-dessus, il est impératif de respecter les règles suivantes.
- La gestion des commentaires ('#')
- Le prolongement d'une commande sur plusieurs lignes (grace au
caractère '\' en fin de ligne)
Partie rémunérée
================
Nous vous rappelons que cette partie sera testée uniquement si vous
avez validé les tests de la partie obligatoire.
Certaines de ces parties entraînent des modifications dans le
comportement de la partie obligatoire. Celles-ci ne sont pas forcément
précisées dans le sujet (par exemple, la gestion de l'expansion des
variables entraîne forcément une modification du quoting).
Il existe pour certaines parties des dépendances, il est nécessaire
que toutes les dépendances précisées soient validées pour que cette
partie soit testée. Par exemple on ne testera même pas votre gestion
du « scripting » si l'expansion des variables n'est pas validée.
1) Redirections avancées
------------------------
# dépendance : aucune
# nombre de points : 1
Ceci concerne la gestion des "here-documents".
Il vous est demandé de gérer les indirections doubles :
- [n]<
- Sujet sous license acu 2004 -
- Toute utilisation pour une promo anterieure a 2005 est prohibee -
|