Pràctica 02: Implementació d’una minishell ohmy_shell en C
La ohmy_shell és una minishell escrita en C que simula el comportament bàsic d’una shell Unix. Es tracta d’un projecte clàssic en molts cursos de Sistemes Operatius arreu del món. Per tant, és possible trobar implementacions similars a Internet, i fins i tot la intel·ligència artificial pot generar codi per ajudar-vos. Tot i així, implementar-la vosaltres mateixos us permetrà entendre el funcionament intern d’una shell real com bash o zsh.
L’objectiu és escriure la vostra pròpia shell interactiva, gestionant manualment la memòria, el comportament dels operadors i la resposta davant errors. Acceptes el repte?
Per començar, heu d’acceptar l’activitat del GitHub Classroom heu d’accedir a l’enllaç següent: Github Classroom. Un cop acceptada, el primer membre del grup assignarà un nom a l’equip i la resta de membres s’hi podran unir. Després, cada membre haurà de clonar el repositori al seu entorn local.
🎯 Objectius
- Comprendre la creació i gestió de processos en entorns Unix mitjançant
fork(),exec*(),pipe(),dup2(),waitpid(),open(),close(). - Reconèixer i programar l’ús de descriptors de fitxer, pipes, redireccions i operadors lògics.
- Desenvolupar la gestió de senyals (SIGINT: Ctrl+C, SIGCHLD: reaprofitar processos fill).
- Implementar parsing: seqüència, pipes, condicions, execució en background.
- Evitar fugues de memòria i descriptors oberts.
- Diferenciar entre comandes internes (built-ins) i externes.
🛠️ Entorn de Desenvolupament
- Llenguatge de programació: C (estàndard C99 o superior).
- Compilador:
gcc. - Eina de construcció:
make. - VM amb Debian.
🗂️ Estructura del Projecte
La següent és l’estructura bàsica del projecte:
├── build
├── include
│ ├── helpers.h
│ └── log.h
├── Makefile
├── README.md
├── src
│ ├── helpers.c
│ ├── log.c
│ └── ohmy_shell.c La llibreria helpers conté una implementació bàsica de funcions útils com la lectura i divisió de línies o la validació de caràcters. Podeu modificar-les o ampliar-les si cal, sempre amb justificació. No es pot canviar el tipus de retorn ni els paràmetres de les funcions existents.
📜 Tasques a realitzar
1. Modes d’entrada: interactiu i no interactiu
Una shell ha de suportar dos modes d’entrada: interactiu i no interactiu.
Mode interactiu: La shell mostra un prompt (
ohmy_shell>) i espera que l’usuari introdueixi comandes. Després d’executar cada comanda, torna a mostrar el prompt. Aquestashellúnicament ha de sortir quan l’usuari introdueixi la comandaexito quan rebi un senyal d’aturada (comCtrl+D) o la senyalSIGKILL../ohmy_shell ohmy_shell> echo hola hola ohmy_shell> pwd /home/usuari ohmy_shell> exitMode no interactiu: La shell rep una comanda com a argument i l’executa directament sense mostrar cap prompt. Després d’executar la comanda, la shell ha de sortir immediatament.
./ohmy_shell -c "echo hola" hola
2. Implementació de comandes internes (built-ins)
Implementa les següents comandes internes sense crear nous processos:
cd: Canvia el directori; només s’executa si rep exactament un argument vàlid.pwd: Mostra el directori actual.help: Mostra ajuda.exit: Tanca la shell.history: Mostra l’historial (màxim 100 línies, FIFO).
Per implementar la comanda history, tens dues opcions:
- Opció bàsica: Emmagatzema les comandes en memòria utilitzant un punter a cadenes.
- Opció avançada: Emmagatzema les comandes en memòria mitjançant una llista enllaçada.
En ambdues opcions, desa les comandes en un fitxer per mantenir-ne la persistència entre sessions (.ohmy_history) abans de sortir de la shell i carrega-les en iniciar-la.
2. Mode educatiu o debug
Implementa un mode educatiu que s’activi amb l’opció -d en iniciar la shell. En aquest mode, la shell ha de mostrar informació detallada sobre cada pas de l’execució, permetent als usuaris comprendre millor el funcionament intern de la shell i facilitar la comprensió dels conceptes explicats en aquesta assignatura com pipes, fork(), exec(), redireccions, etc.
Exemple:
./ohmy_shell -d
12:00:00 DEBUG ohmy_shell.c:45: Starting shell in debug mode
ohmy_shell> ls -la
12:00:05 DEBUG ohmy_shell.c:78: Forking process for command 'ls -la'
12:00:05 DEBUG ohmy_shell.c:85: Executing command 'ls -la' with PID 12345
(total output of ls -la)
12:00:06 DEBUG ohmy_shell.c:95: Command 'ls -la' completed with exit status 0
ohmy_shell>3. Gestió de processos i execució
La shell ha de ser capaç de crear nous processos per executar comandes externes. La shell ha de permetre gestionar comandes simples en foreground i background.
Comandes en foreground: La shell ha d’esperar que la comanda acabi abans de tornar a mostrar el prompt.
ohmy_shell> sleep 5 (espera 5 segons) ohmy_shell>Comandes en background: Si una comanda acaba amb
&, la shell ha de crear un procés fill per executar la comanda en background i tornar immediatament el prompt a l’usuari sense esperar que la comanda acabi.ohmy_shell> sleep 10 & [1] 12345 ohmy_shell>Gestió d’operadors: Implementa els operadors
&&,||i;per permetre l’execució condicional i seqüencial de comandes.ohmy_shell> mkdir test && cd test ohmy_shell> false || echo "La comanda ha fallat" La comanda ha fallat ohmy_shell> echo "Primera comanda"; echo "Segona comanda" Primera comanda Segona comandaNota: La prioritat d’execució dels operadors és la següent:
;té la prioritat més baixa, seguit de&&i||que tenen la mateixa prioritat i s’executen d’esquerra a dreta.Gestió de senyals: La shell ha de gestionar correctament les senyals
SIGINT(Ctrl+C) iSIGCHLDper evitar processos zombis.- Quan l’usuari prem
Ctrl+C, la shell ha de capturar la senyal i no tancar-se, sinó que ha de mostrar el prompt novament. - Quan un procés fill acaba, la shell ha de capturar la senyal
SIGCHLDi reaprofitar el procés fill per evitar processos zombis.
- Quan l’usuari prem
4. Pipes i Redireccions
La shell ha de suportar l’ús de pipes (|) per connectar la sortida d’una comanda amb l’entrada d’una altra, així com redireccions d’entrada (<), sortida (>), i sortida en mode append (>>).
Exemple:
ohmy_shell> cat fitxer.txt | grep "cerca"
(Mostra línies del fitxer que contenen "cerca")
ohmy_shell> echo "hola" > out.txt
(La sortida s'escriu a 'out.txt')
ohmy_shell> echo "més text" >> out.txt
(El text s'afegeix al final de 'out.txt')
ohmy_shell> sort < in.txt
(Mostra el contingut de 'in.txt' ordenat)5. Variables d’entorn
La shell ha de permetre als usuaris establir i utilitzar variables d’entorn. Implementa la funcionalitat per assignar valors a variables i utilitzar-les en comandes.
Exemple:
ohmy_shell> MYVAR="Hola Món"
ohmy_shell> echo $MYVAR
Hola MónLes variables d’entorn s’han de gestionar correctament, permetent als usuaris establir, modificar i eliminar variables segons sigui necessari. Aquestes variables s’hereten del procés del procés bash que ha iniciat l’aplicació ohmy_shell. Les variables no definides es tractaran com a cadenes buides.
6. Comentaris a la línia de comandes
La shell ha de permetre als usuaris afegir comentaris a les línies de comandes utilitzant el caràcter #. Tot el que segueixi al caràcter # en una línia de comandes ha de ser ignorat per la shell.
BONUS
Implementa almenys una de les següents funcionalitats addicionals per obtenir el bonus:
Configuració personalitzada del historial: Permet als usuaris configurar la mida màxima de l’historial i el fitxer on es desa. Exemple:
ohmy_shell> set_history_size 200 ohmy_shell> set_history_file ~/.my_custom_historyPermetre l’ús de comandes compostes amb parèntesis per agrupar comandes i controlar l’ordre d’execució. Exemple:
ohmy_shell> (echo "Inici"; ls -la; echo "Fi") Inici (sortida de ls -la) FiAutomatitza l’avaluació de la teva shell mitjançant un script de proves que verifiqui totes les funcionalitats implementades. L’script pot ser senzill i comparar la sortida esperada amb la sortida real de la shell en diversos casos de prova.
💯 Avaluació i Criteris de Qualitat
Per avaluar el projecte, es tindran en compte els següents aspectes:
| Aspecte | Puntuació Màxima |
|---|---|
Core |
40 |
Avançada |
30 |
Qualitat del codi |
20 |
Documentació |
10 |
Bonus |
10 |
Core: inclou la implementació d’una shell capaç d’executar comandes simples, gestionar processos en foreground i background, implementar les comandes internes especificades, i gestionar redireccions i pipes.
Avançada: inclou l’ús d’operadors lògics (&&, ||, ;), variables d’entorn, comentaris, mode debug i historial de comandes.
Qualitat del codi: s’utilitzarà Valgrind i eines de linting per avaluar la qualitat del codi, assegurant que no hi hagi fugues de memòria, accessos fora de límits i que es segueixin les bones pràctiques de programació en C, com:
- Net i ben estructurat, evitant funcions repetides o codi duplicat innecessari.
- Comentat adequadament, amb noms de variables descriptius.
- Documentat segons estàndards com Doxygen (opcional però recomanat).
- Ús correcte i raonable del git amb commits clars i descriptius, gestió d’issues i generació de release amb la versió final del projecte.
Bonus: s’atorgarà per la implementació de funcionalitats addicionals com la configuració personalitzada de l’historial o l’ús de comandes compostes amb parèntesis.
Documentació: s’avaluarà la professionalitat i el contingut del fitxer
README.md:- Com compilar i executar el projecte.
- Com utilitzar-lo amb exemples en format video o imatges.
- Distribució de tasques entre els membres de l’equip (si escau).
- Disseny i arquitectura del projecte.
🚫 Prohibicions
No podeu utilitzar la funció
system()per executar comandes externes, ni cap altre programa que realitzi la mateixa funció. Tota pràctica que no gestioni processos ambfork(),exec(), etc., serà considerada com a no realitzada.Qualsevol instrucció no vista a classe s’ha de justificar. Si existeix alguna comanda vista a classe amb la mateixa finalitat i s’utilitza una altra, això suposarà una penalització de la nota. Totes les funcions de
string.haixí com de totes les llibreries que teniu incloses al projecte són permeses.
📅 Planificació i versions
| Entrega | Versio | Contingut |
|---|---|---|
| 16-11-2025 | 1.0 | Implementació bàsica de la shell amb built-in, comandes simples |
| 23-11-2025 | 2.0 | Pipes, redireccions, background |
| 30-11-2025 | 3.0 | Historial |
| 07-12-2025 | 4.0 | Operadors lògics, variables d’entorn, comentaris, mode debug |
Aquesta pràctica és extensa i complexa, per això us recomano seguir la planificació proposada. Si feu una petita entrega cada setmana, us podré oferir feedback i tindreu l’oportunitat de corregir possibles errors abans de la data final de lliurament. Aquesta opció és voluntària; també podeu presentar la pràctica completa al final, segons el vostre ritme de treball.
La nota d’aquesta pràctica tindrà un pes doble (ponderada per 2), ja que equival a dues pràctiques en una i disposeu d’un mes per completar-la.
❓ Suport i Consultes
He creat un fòrum al Campus Virtual per resoldre dubtes i incidències relacionades amb aquesta pràctica. Us demano que utilitzeu aquest canal per centralitzar les consultes i evitar duplicitats en preguntes i respostes. També podeu ajudar a resoldre els dubtes dels companys: supervisaré totes les aportacions i corregiré qualsevol informació incorrecta si cal.
📦 Lliurament
- Tot el projecte al repositori GitHub assignat.
makeha de compilar sense errors ni warnings.- S’avaluarà només la branca principal (
mainomaster).
Per formalitzar el lliurament al Campus Virtual, copieu i enganxeu el text corresponent a la caixa de text de lliurament del Campus:
Individual o Grupal: [Indicar si és Individual o Grupal]
<Si Grupal>
Membres: [Llista de Noms, incloent el teu]
Team: [Nom del Team al Classroom]
Happy Coding! 🚀