This shows you the differences between two versions of the page.
sde:teme:tema_ro_3_python [2020/03/04 13:18] ioana_maria.culic [Reguli] |
— (current) | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== Tema 3 - Mini-shell ====== | ||
- | |||
- | Scopul acestei teme este realizarea unui shell simplu, compatibil cu ''sh''; | ||
- | |||
- | ===== Informații generale ===== | ||
- | |||
- | <note important> | ||
- | Deadline: **31 Martie, ora 23:55**\\ | ||
- | Punctaj: **2 puncte** din nota\\ | ||
- | Incarcarea temei: [[https://vmchecker.cs.pub.ro|vmchecker.cs.pub.ro]]\\ | ||
- | Incarcarea cu intarziere: **0.1 punct / zi** (maxim 4 zile)\\ | ||
- | </note> | ||
- | |||
- | ===== Cunoștințe evaluate ===== | ||
- | |||
- | * Folosirea functiilor POSIX pentru lucrul cu fisiere (''os.open'', ''os.read'', ''os.write'', ...) | ||
- | * Folosirea functiilor pentru lucrul cu procese (''os.fork'', ''os.exec'' si ''os.waitpid'', ...) | ||
- | * Intelegerea principiilor de lucuru cu fisier si procese | ||
- | |||
- | ===== Reguli ===== | ||
- | |||
- | - Tema trebuie sa contina un fisier Readme in care sa explicati cum ati facut tema (-0.1p) | ||
- | - Aveti voie sa folositi doar functii POSIX (biblioteca os) | ||
- | - Aveti voie sa folositi doar limbajul Python (Python 3) | ||
- | - O temă care trece toate testele automate va obține 10 puncte din 10 (daca nu trișează folosind API interzis, cum ar fi funcția ''f.write()'', caz în care nu va fi punctată). | ||
- | |||
- | |||
- | ===== Copierea ===== | ||
- | |||
- | Tema se rezolva individual. Orice tentativa de copiere va rezulta in **0p** pentru tema respectiva. Vom utiliza si sisteme automate de detectare a copierii. Daca avem dubii, va vom adresa intrebari suplimentare legate de tema. | ||
- | |||
- | ===== Intrebari ===== | ||
- | |||
- | Daca aveti intrebari legate de tema, va rugam sa scrieti un issue pe repository-ul de github [[https://github.com/upb-fils/sde.git|repository]] cu titlul de forma //[mini-shell] <titlul intrebarii voastre>//. Aveti nevoie de un cont de github pentru | ||
- | a scrie intrebari. | ||
- | |||
- | <note warning> | ||
- | **NU PUBLICATI COD SURSA**. Acesta va fi considerata copiere si se va penaliza cu 0p pe tema pentru voi. | ||
- | </note> | ||
- | |||
- | Daca doriti sa primiti un email cand se pun intrebari noi sau cand apar raspunsuri, accesati github [[https://github.com/upb-fils/sde|repository]] si faceti click pe //Watch//. | ||
- | |||
- | ===== Mini Shell ===== | ||
- | |||
- | Să se implementeze un shell simplu, care suportă execuția de comenzi externe cu argumente multiple, comenzi interne, redirectări, pipe-uri. Shell-ul trebuie să suporte execuția de comenzi compuse, cu oricâți operatori. | ||
- | |||
- | <note> | ||
- | Comnezi interne: comenzi pe care shell-ul le execute: ''cd'', ''pwd'', ''exit'' ... | ||
- | Comenzi externe: comenzi care sunt de fapt executabile separate: ''ls'', ''vim'', ''tree'', ''nano'', ... | ||
- | |||
- | Regula este asa: se verifica daca este comanda interna, daca nu, se presupune ca este o comanda externa. | ||
- | </note> | ||
- | |||
- | Shell-ul trebuie să suporte următorii operatori de execuție: | ||
- | |||
- | *operatorul de secvențiere '';'' | ||
- | *va fi folosit pentru a executa comenzile "pe rând"; | ||
- | *de exemplu, ''expr1; expr2'' va avea ca efect mai întâi execuția comenzilor ''expr1'' și, după terminarea execuției acestora, execuția comenzilor ''expr2''; | ||
- | *operatorul de paralelism ''&'' | ||
- | *va fi folosit pentru a executa comenzile în paralel; | ||
- | *de exemplu, ''expr1 & expr2'' va avea ca efect execuția comenzilor ''expr1'' și a comenzilor ''expr2'' în paralel; | ||
- | *în implementare **NU** aveți voie să vă reapelați singuri executabilul. <code>execv("./my_homework", "command");</code> | ||
- | *operatorii de execuție condiționată ''&&'' și ''||'' | ||
- | *vor fi folosiți pentru a executa comenzile în funcție de codul de eroare; | ||
- | *''expr1 && expr2'' va avea ca efect execuția comenzilor ''expr2'' doar în cazul în care comenzile ''expr1'' au ca rezultat un cod de eroare ''0''; | ||
- | *''expr1 || expr2'' va avea ca efect execuția comenzilor ''expr2'' doar în cazul în care comenzile ''expr1'' au ca rezultat un cod de eroare diferit de zero. | ||
- | * operatorul pipe ''|'' este interpus intre doua comenzi. Efectul este redirectionarea a ceea ce scrie pe ecran primul proces | ||
- | spre ceea ce citeste de la tastatura al doilea proces. De exemplu, ''expr1 | expr2'' va avea ca efect execuția comezilor ''expr1'' cu stdout-ul redirectat în stdin-ul comenzilor ''expr2''; | ||
- | |||
- | |||
- | Prioritatea operatorilor de execuție este, de la cel mai prioritar la cel mai puțin prioritar: | ||
- | |||
- | - operatorul pipe | ||
- | - operatorii de execuție condiționată | ||
- | - operatorul de paralelism | ||
- | - operatorul de secvențiere | ||
- | |||
- | Shell-ul trebuie, de asemenea, să suporte și următorii operatori de redirectare: | ||
- | |||
- | *''< nume_fisier'' pentru redirectarea intrării standard din fișierul ''nume_fisier''; | ||
- | *''> nume_fiser'' pentru redirectarea ieșirii standard în fișierul ''nume_fisier''; | ||
- | *''2> nume_fisier'' pentru redirectarea ieșirii de eroare standard în fișierul ''nume_fisier''; | ||
- | *''&> nume_fisier'' pentru redirectarea ieșirii standard și ieșirii de eroare standard în fișierul ''nume_fisier''; | ||
- | *''%%>>%% nume_fisier'' pentru redirectarea ieșirii standard în fișierul ''nume_fisier'' în modul //append//; | ||
- | *''2%%>>%% nume_fisier'' pentru redirectarea ieșirii de eroare standard în fișierul ''nume_fisier'' în modul //append//. | ||
- | |||
- | În fine, shell-ul trebuie să suporte următoarele comenzi interne: | ||
- | |||
- | *''exit'' și ''quit'' pentru terminarea shell-ului | ||
- | *''cd director'' pentru schimbarea directorului curent | ||
- | * **ATENȚIE**: Mini-shell-ul trebuie să funcționeze în continuare la introducerea comenzii ''cd'' fără parametru. Nu se impune implementarea comportamentului din ''bash'' (schimbarea directorului curent cu directorul //home// al utilizatorului curent) și nici o valoare de exit pentru acest scenariu (practic, ''cd'' fără parametru poate să nu facă nimic, dar să nu rămână cu comportament nedefinit care să ducă la erori). | ||
- | |||
- | Shell-ul trebuie să suporte variabile de mediu: | ||
- | *formatul de utilizare este ''$VARIABILA_DE_MEDIU'' identic pe Linux și pe Windows | ||
- | *variabilele de mediu sunt moștenite de la shell-ul părinte (Bash) sau sunt definite în mini-shell | ||
- | *definirea variabilelor se face sub forma ''NUME_VARIABILA=valoare'' | ||
- | *trebuie tratat și cazul în care ''valoare'' conține referiri la alte variabile de mediu | ||
- | *dacă variabila de mediu nu există, aceasta are valoarea șirul vid (**Atenție** șirul vid este diferit de NULL) | ||
- | |||
- | ==== Precizări generale ==== | ||
- | |||
- | *Pentru a simplifica implementarea temei, puteți folosi [[#parcurgearea linii de comanda | parserul]] implementat de noi. Pentru detalii despre parser, citiți fișierul ''README'' din arhivă. Exemple de utilizare a parserului găsiți în sursa ''CUseParser.c''. | ||
- | *Promptul afișat de shell este impus pentru a facilita testarea automată și este \$ (adică se va afișa caracterul $ urmat de un spațiu). | ||
- | *Numele executabilului temei trebuie să fie ''mini-shell''. | ||
- | |||
- | ==== Sugestii de rezolvare ==== | ||
- | Tema este relativ complexa fata de cea anterioara. Un sablon pentru inceperea temei este disponibil in [[https://github.com/upb-fils/sde|repository]] in directorul //tema3//. | ||
- | |||
- | Recomandăm rezolvarea și testarea din aproape în aproape a temei, după pași: | ||
- | |||
- | - rularea de comenzi simple (''ls'', ''ls -l'') | ||
- | - rularea de comenzi interne (''cd'', ''exit'', ''quit'') | ||
- | - implementarea redirectărilor (operatorii ''<'', ''>'', ''2>'', ''&>'', ''%%>>%%'', ''2%%>>%%'') | ||
- | - secvențierea comenzilor (operatorii ''&&'', ''||'', '';'') | ||
- | - implementarea operatorilor ''&'' (paralel) | ||
- | - ''|'' | ||
- | |||
- | *Aveți mai jos câteva exemple de comenzi și rezultatul generat de acestea: | ||
- | <code bash> | ||
- | $ 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</code> | ||
- | |||
- | ===== Materiale ajutătoare ===== | ||
- | Cursuri utile: | ||
- | *[[sde:cursuri:01]] | ||
- | *[[sde:cursuri:02]] | ||
- | *[[sde:cursuri:03]] | ||
- | *[[sde:cursuri:04]] | ||
- | *[[sde:cursuri:05]] | ||
- | |||
- | Laboratoare utile: | ||
- | *[[sde:laboratoare:01]] | ||
- | *[[sde:laboratoare:02_ro]] | ||
- | *[[sde:laboratoare:03_ro]] | ||
- | *[[sde:laboratoare:04_ro]] | ||
- | *[[sde:laboratoare:05_ro]] | ||
- | |||
- | Resurse: | ||
- | * Parserul pentru comenzi, sablonul de cod și testele sunt disponibile în directorul [[https://github.com/upb-fils/sde/tree/master/tema3| tema3]] din [[https://github.com/upb-fils/sde|repo-ul de pe Github]]. | ||
- | |||
- | |||
- | ===== Parcurgerea linii de comanda ===== | ||
- | Pentru parcurgerea linii de comanda, am scris noi deja un parser pe care il puteti folosi. | ||
- | Incepeti tema in fisierul ''cmd.c'' aflat in sablon. | ||
- | |||
- | Pentru a vizualiza cum arata structura de date primita de la parser, folositi urmatoarele: | ||
- | |||
- | <code bash> | ||
- | make DisplayStructure # Compileaza DisplayStructure | ||
- | ./DisplayStructure # ruleaza DisplayStructure | ||
- | |||
- | # exemplu de comanda simpla | ||
- | # op este OP_NONE iar scmd are un pointer catre o structura simple_command_t | ||
- | # comanda este in cmd->scmd->verb (acesta este un string) | ||
- | |||
- | $ ls | ||
- | ls | ||
- | Command successfully read! | ||
- | command_t ( | ||
- | op == OP_NONE | ||
- | scmd ( | ||
- | simple_command_t ( | ||
- | verb ( | ||
- | 'ls' | ||
- | ) | ||
- | ) | ||
- | ) | ||
- | ) | ||
- | |||
- | # idem cu comanda de mai sus, doar ca exista si parametrii (array de string-uri) | ||
- | |||
- | $ ls -l | ||
- | ls -l | ||
- | Command successfully read! | ||
- | command_t ( | ||
- | op == OP_NONE | ||
- | scmd ( | ||
- | simple_command_t ( | ||
- | verb ( | ||
- | 'ls' | ||
- | ) | ||
- | params ( | ||
- | '-l' | ||
- | ) | ||
- | ) | ||
- | ) | ||
- | ) | ||
- | |||
- | # idem cu mai sus, insa cu doi parametrii | ||
- | $ ls -r -l | ||
- | ls -r -l | ||
- | Command successfully read! | ||
- | command_t ( | ||
- | op == OP_NONE | ||
- | scmd ( | ||
- | simple_command_t ( | ||
- | verb ( | ||
- | 'ls' | ||
- | ) | ||
- | params ( | ||
- | '-r' | ||
- | '-l' | ||
- | ) | ||
- | ) | ||
- | ) | ||
- | ) | ||
- | |||
- | # doua comanezi inlantuite | ||
- | $ ls ; ls /etc | ||
- | ls ; ls /etc | ||
- | Command successfully read! | ||
- | command_t ( | ||
- | op == OP_SEQUENTIAL | ||
- | cmd1 ( | ||
- | command_t ( | ||
- | op == OP_NONE | ||
- | scmd ( | ||
- | simple_command_t ( | ||
- | verb ( | ||
- | 'ls' | ||
- | ) | ||
- | ) | ||
- | ) | ||
- | ) | ||
- | ) | ||
- | cmd2 ( | ||
- | command_t ( | ||
- | op == OP_NONE | ||
- | scmd ( | ||
- | simple_command_t ( | ||
- | verb ( | ||
- | 'ls' | ||
- | ) | ||
- | params ( | ||
- | '/etc' | ||
- | ) | ||
- | ) | ||
- | ) | ||
- | ) | ||
- | ) | ||
- | ) | ||
- | |||
- | </code> | ||
- | |||
- | ===== FAQ ===== | ||
- | |||
- | ***Q:** Tema 3 se poate face în C++? | ||
- | ***A:** Nu. | ||
- | |||
- | ***Q:** Trebuie optimizat numărul de fork-uri? Spre exemplu, în cazul comenzii ''a|b|c'' trebuie sa am 3 forkuri sau pot să am 4 sau 5? | ||
- | ***A:** Nu este obligatoriu să optimizați numărul de fork-uri. Totuși, în general este bine să aveți în vedere eficientizarea consumului de resurse. | ||
- | |||
- | ***Q:** Shell-ul trebuie să se comporte ca un shell adevărat (sh, bash) în situația ... ? | ||
- | ***A:** Funcționalitatea minimă necesară este cea din enunțul temei. Daca implementați ceva în plus, precizați în README. Exemple de funcționalitate care nu este cerută: updatarea unor variabile de mediu (gen ''$OLDPWD'' și ''$PWD''), history, multe altele ... (vezi [[http://linux.die.net/man/1/bash | man bash]] pentru o idee despre funcționalitatea unui shell complet :-) ) | ||
- | |||
- | ***Q:** Am voie să nu folosesc parserul din enunț dacă doresc să scriu eu altul echivalent? | ||
- | ***A:** Da. | ||
- | |||
- | ***Q:** Avem voie sa folosim: <code> | ||
- | const char *argv[] = {"/bin/bash", "-c", command, NULL}; | ||
- | execv("/bin/bash", (char *const *)argv); | ||
- | </code> | ||
- | ***A:** Nu. | ||
- | |||
- | ***Q:** Am voie să fac ''execv'' pe tema mea pentru a executa o parte din arbore independent? | ||
- | ***A:** Nu. | ||
- | |||
- | |||
- | ===== Trimiterea temei ===== | ||
- | Tema se va incarca pe [[https://vmchecker.cs.pub.ro|vmchecker]]. Logati-va pe site cu folosind utilizatorul de pe moodle, selectati cursul //Systemes d'Explotation (FILS)// si incarcati [[#arhiva-temei|arhiva temei]]. | ||
- | |||
- | ==== Readme ==== | ||
- | Fisierul readme are urmatorul format: | ||
- | |||
- | <code> | ||
- | Numele vostru intreg | ||
- | Grupa | ||
- | |||
- | Descrierea rezolvarii temei, de ce ati ales anumite solutii, etc. | ||
- | </code> | ||
- | |||
- | |||
- | ==== Arhiva temei ==== | ||
- | Pentru a incarca tema, urmariti pasii: | ||
- | |||
- | - Creati o arhiva zip (nu rar, ace, 7zip sau alt fomrat) care sa contina: | ||
- | * toate fisierele header (*.h) | ||
- | * toate fisierele sursa (*.c) | ||
- | * fisierul Makefile (este deja facut in sablonul temei) | ||
- | * fisierul Readme | ||
- | - logati-va pe [[https://vmchecker.cs.pub.ro|vmchecker]] | ||
- | - selectati cursul //Systemes d'Explotation(FILS)// | ||
- | - selectati //3. Mini-Shell// | ||
- | - incarcati arhiva | ||
- | |||
- | |||
- | <note> | ||
- | Arhiva trebuie sa contina toate fisierele (principale) in radacina, nu in subdirectoare. NU arhivati directorul temei, arhivati DIRECT fisierele. | ||
- | |||
- | NU includeti fisierele obiect (*.o) si executabilul. (Sfat: folositi //make clean// pentru a sterge acestea inainte de arhivarea temei) | ||
- | </note> | ||
- | |||
- | Dupa ce incarcati arhiva, vmchecker va rula: | ||
- | |||
- | <code bash> | ||
- | unzip archive.zip homework | ||
- | cd homework | ||
- | make build | ||
- | make run | ||
- | </code> | ||
- | |||
- | |||
- | |||
- | |||