Le but de ce thème est de créer un shell simple, compatible avec sh
;
fork
, exec
et waitpid
, …)Le devoir doit etre résolu individuellement. Toute tentative de tricher entraînera 0p pour ce devoir. Nous utiliserons également des systèmes de détection de trichage automatique. Si nous avons des doutes, nous vous poserons des questions supplémentaires concernant le devoir.
Si vous avez des questions concernant le devoir, posez-les en publiant un issue sur le github https://github.com/UPB-FILS-SdE2/questions avec le format [busybox] <le titre de votre question> . Vous aurez besoin d'un compte github pour publier des questions.
Si vous voulez recevoir un e-mail lorsque des problèmes sont signalés ou lorsqu'il y a de nouveaux messages, accédez au site github repository et cliquez sur Watch.
Implémentez un shell simple qui prend en charge l'exécution de commandes externes avec plusieurs arguments, commandes internes, redirections, canaux. Le shell doit gérer l'exécution de commandes composées avec plusieurs opérateurs.
cd
, pwd
, exit
…
Commandes externes: Les commandes qui sont en fait des exécutables séparés: ls
, vim
, arbre
, nano
, …
La règle est la suivante: vérifiez si la commande interne est, sinon, on suppose qu'elle est une commande externe.
Le shell doit prendre en charge les opérateurs d'exécution suivants:
;
expr1; expr2
commencera par exécuter les commandes expr1
et les commandes expr2
seulement après l'exécution de expr1; &&
et ||
expr1 && expr2
n'exécutera les commandes expr2
que si la commande expr1
génère un code d'erreur '0' '; expr1 || expr2
n'exécutera les commandes expr2
que si les commandes expr1
génèrent un code d'erreur différent de zéro. |
est interpolé entre deux commandes. L'effet est la redirection de ce que le premier processus écrit sur l'écran vers ce que le deuxieme processus lit du clavier . Par exemple, expr1 | expr2
entraînera l'exécution des commandes expr1
avec la sortie standard redirigée vers le stdin des commandes expr2
;La priorité des opérateurs d'exécution est, de la priorité la plus grande à la plus petite:
Le shell doit également prendre en charge les redirecteurs suivants:
< nom_fichier
pour rediriger l'entrée standard à partir du fichier nom_fichier
; > nom_fichier
pour rediriger la sortie standard vers le fichier nom_fichier
; 2> nom_fichier
pour rediriger la sortie d'erreur standard vers le fichier nom_fichier
; &> nom_ficher
pour rediriger la sortie standard et la sortie d'erreur standard vers le fichier nom_fichier
; >> nom_fichier
pour rediriger la sortie standard vers le fichier nom_fichier
en mode append ; 2 >> nom_fichier
pour rediriger la sortie d'erreur standard vers le fichier nom_fichier
en mode append .Finalement, le shell doit accepter les commandes internes suivantes:
exit
et quit
pour terminet le shell cd directory
pour changer le répertoire actuel cd
sans paramètre, remplacer le répertoire en cours par le répertoire home de l'utilisateur courant (variable $HOME)Le shell doit aussi supporter les sous-commandes:
commande $(commande ou liste commandes)
Le devoir est relativement complexe par rapport au précédent. Un modèle pour le commencement du devoir est disponible sur le repository dans le répertoire tema3 . Nous vous recommandons de résoudre et de tester toujours le devoir, étape par étape:
ls
, ls -l
) cd
, exit
, quit
) <
, >
, 2>
, &>
, »
, 2»
)&&
, ||
, ;
) &
(parallèle, pas utilise) |
$ ls Makefile README.checker mini-shell mini-shell.o parser Makefile.checker inputs mini-shell.c outputs tags $ cat /etc/services | grep telnet telnet 23/tcp rtelnet 107/tcp # Remote Telnet rtelnet 107/udp telnets 992/tcp # Telnet over SSL telnets 992/udp tfido 60177/tcp # fidonet EMSI over telnet $ uname -a ; ps Linux bogdan-desktop 2.6.31-19-generic #56-Ubuntu SMP Thu Jan 28 02:39:34 UTC 2010 x86_64 GNU/Linux PID TTY TIME CMD 6078 pts/0 00:00:00 bash 6190 pts/0 00:00:00 mini-shell 6200 pts/0 00:00:00 ps $ date && sleep 1 ; echo date Mon Feb 8 13:40:25 EET 2010 date $ date && sleep 1; date Mon Feb 8 13:40:49 EET 2010 Mon Feb 8 13:40:50 EET 2010 $ true && date Mon Feb 8 13:41:16 EET 2010 $ false && cat mini-shell.c $ false || date Mon Feb 8 13:42:36 EET 2010 $ cat /et/services cat: /et/services: No such file or directory $ gcc > tmp; echo sep; cat tmp gcc: no input files sep $ strace -e trace=read ls 2> strace.out Makefile README.checker mini-shell mini-shell.o parser tags Makefile.checker inputs mini-shell.c outputs strace.out tmp $ head -1 strace.out read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0@#\0\0\0\0\0\0@"..., 832) = 832 $ pwd; cd Teme; pwd /home/bogdan/Documents/SO/Solutii /home/bogdan/Documents/SO/Solutii/Teme $ LETTER=alfa && echo $LETTER alfa > echo a > test ; echo b >> test && cat test a b > exit
Cours utiles:
Laboratoires utiles:
Pour traiter la ligne de commande, nous avons déjà écrit un analyseur que vous pouvez utiliser.
Pour voir à quoi ressemble la structure de données à partir de l'analyseur, exécutez le modèle et apres introduisez une commande du clavier.
$ cargo run $ ls Command "ls" SimpleCommand { assignments: [], parameters: [ [ Word( "ls", ), ], ], redirects: [], } $ ls && echo "folder exists" Command "ls && echo \"folder exists\"" AndCommand( SimpleCommand { assignments: [], parameters: [ [ Word( "ls", ), ], ], redirects: [], }, SimpleCommand { assignments: [], parameters: [ [ Word( "echo", ), ], [ Quotes( [ [ Word( "folder", ), ], [ Word( " ", ), ], [ Word( "exists", ), ], ], ), ], ], redirects: [], }, )
Pour comprendre comment utiliser la structure renvoyée par l'analyseur, exécutez la commande cargo doc –open
et examinez le module parser::ast.