save commit

This commit is contained in:
2026-02-09 20:47:43 +01:00
parent e983f7fe64
commit 280fa51f94
39 changed files with 3400 additions and 239 deletions

292
docs/guia_obligatoria_es.md Normal file
View File

@@ -0,0 +1,292 @@
# Minishell - Guia de estructura y pasos (parte obligatoria)
Objetivo de este documento
- Proponer una estructura de archivos y datos.
- Describir el proceso paso a paso como tutorial.
- Servir de guion para defensa (explicaciones claras y ordenadas).
Este documento no implementa nada. Solo define el plan y el por que.
---
## 1. Vision general del flujo
El shell se puede explicar como una tuberia de fases:
1. Lectura interactiva (prompt + historial).
2. Tokenizacion (lexing) con comillas y metacaracteres.
3. Parseo (construccion de comandos, redirecciones, pipes).
4. Expansion de variables ($VAR y $?).
5. Preparacion de ejecucion (resolucion de rutas, heredoc).
6. Ejecucion (builtins o execve) con pipes y redirecciones.
7. Gestion de exit status y señales.
Esta separacion permite explicar en defensa cada pieza por separado y justificar
las decisiones tecnicas.
---
## 2. Propuesta de estructuras de datos
Estas estructuras son solo guia. Adapta nombres a tu estilo y Norminette.
### 2.1 Token (lexer)
Representa una unidad del input (palabra, pipe, redireccion, etc.).
- enum e_tokentype
- TOK_WORD
- TOK_PIPE
- TOK_REDIR_IN (<)
- TOK_REDIR_OUT (>)
- TOK_REDIR_APPEND (>>)
- TOK_HEREDOC (<<)
- struct s_token
- char *text
- t_tokentype type
- struct s_token *next
Uso en defensa: el lexer separa el input en unidades, respetando comillas.
### 2.2 Redireccion
Guarda los datos de redireccion por comando.
- enum e_redirtype
- REDIR_IN
- REDIR_OUT
- REDIR_APPEND
- REDIR_HEREDOC
- struct s_redir
- t_redirtype type
- char *target
- int fd
- struct s_redir *next
Notas:
- target es el filename o delimitador de heredoc.
- fd se resuelve en fase de preparacion (open o pipe temporal).
### 2.3 Comando
- struct s_command
- char **argv
- int argc
- char *path
- t_redir *redirs
### 2.4 Pipeline
Una lista de comandos en orden, unidos por pipes.
- struct s_pipeline
- t_command **cmds
- size_t count
---
## 3. Lexer: reglas y pasos
Reglas clave del subject:
- No interpretar comillas sin cerrar.
- Comilla simple: no se expanden variables ni metacaracteres.
- Comilla doble: se expanden variables, pero se respetan caracteres normales.
- Metacaracteres: |, <, >, <<, >> separan tokens.
Pasos recomendados:
1. Recorrer la linea caracter a caracter.
2. Mantener estado: in_single, in_double.
3. Cuando no estas en comillas, detectar metacaracteres y cortar tokens.
4. Construir TOK_WORD con el texto exacto (sin eliminar comillas aun).
5. Si llegas a fin de linea con in_single o in_double activo, error de parseo.
Explicacion para defensa:
- El lexer no sabe de ejecucion, solo separa en tokens validos.
- El manejo de comillas se hace aqui para respetar la sintaxis del shell.
---
## 4. Parser: construccion de comandos
Objetivo: transformar tokens en una estructura ejecutable.
Pasos:
1. Recorrer lista de tokens.
2. Cada TOK_PIPE cierra un comando actual y abre el siguiente.
3. TOK_WORD se agrega a argv.
4. TOK_REDIR_* consume el siguiente token (debe ser TOK_WORD) como target.
5. Construir lista de redirecciones para cada comando.
6. Validar errores: pipe inicial/final, redireccion sin target, etc.
Explicacion para defensa:
- El parser aplica reglas de orden y construye una estructura clara.
- Separar argv y redirecciones evita mezclar logica en executor.
---
## 5. Expansion de variables
Reglas:
- $VAR se sustituye por getenv/tabla interna.
- $? se sustituye por el exit_status anterior.
- En comilla simple no se expande.
- En comilla doble si se expande.
Proceso recomendado:
1. Durante tokenizacion, guardar el texto con sus comillas o bien
marcar segmentos con estado de comillas.
2. En expansion, recorrer cada palabra y reemplazar $...
3. Si variable no existe, reemplazar por string vacio.
4. Eliminar comillas despues de la expansion.
Explicacion para defensa:
- La expansion es una fase separada para no complicar el parser.
- $?, variable especial, refleja el estado de la ultima ejecucion.
---
## 6. Redirecciones y heredoc
Redirecciones basicas:
- <: open(file, O_RDONLY)
- >: open(file, O_WRONLY | O_CREAT | O_TRUNC)
- >>: open(file, O_WRONLY | O_CREAT | O_APPEND)
Heredoc (<<):
1. Leer lineas hasta delimitador exacto.
2. Guardar el contenido en un pipe o fichero temporal.
3. Usar el extremo de lectura como STDIN del comando.
4. No guardar el contenido en historial.
Explicacion para defensa:
- Las redirecciones se resuelven antes de ejecutar el proceso.
- Heredoc es una fuente especial de entrada.
---
## 7. Resolucion de comandos y PATH
Reglas:
- Si argv[0] es una ruta absoluta o relativa (/, ./, ../), usarla tal cual.
- Si no, buscar en PATH separando por ':'.
- Si es builtin, no se necesita path real.
Proceso:
1. Detectar builtin.
2. Si no builtin y no es ruta, recorrer PATH y usar access().
3. Guardar path en t_command->path.
---
## 8. Ejecucion
Caso 1: comando unico builtin
- Ejecutar en el proceso padre para que pueda modificar estado del shell
(ej: cd, export, unset, exit).
Caso 2: pipeline o comando externo
- Usar fork + execve.
- Crear pipes entre comandos.
- Aplicar redirecciones antes de ejecutar.
Proceso para pipeline:
1. Para cada comando, crear pipe si hay siguiente.
2. fork.
3. En child: dup2 para redirecciones y pipes, luego ejecutar.
4. En parent: cerrar FDs innecesarios y seguir.
5. Esperar procesos, guardar exit status del ultimo comando.
Explicacion para defensa:
- Las pipes conectan stdout del comando i con stdin del comando i+1.
- Los builtins dentro de pipeline se ejecutan en child.
---
## 9. Builtins obligatorios
- echo con -n
- cd (ruta relativa o absoluta)
- pwd
- export (sin opciones)
- unset (sin opciones)
- env (sin opciones o argumentos)
- exit
Notas de defensa:
- export/unset trabajan sobre la tabla de variables del shell.
- env imprime variables de entorno.
- exit debe actualizar exit_status y terminar el loop principal.
---
## 10. Senales
Requisitos interactivos:
- ctrl-C: imprime nueva linea y muestra prompt.
- ctrl-D: termina el shell.
- ctrl-\: no hace nada.
Regla del subject:
- Solo una variable global para indicar la senal recibida.
Proceso:
1. Definir una variable global int g_signal.
2. Configurar handlers con sigaction.
3. En handler: actualizar g_signal y escribir un '\n' si procede.
4. En el loop principal: si g_signal indica SIGINT, resetear lineas de readline.
---
## 11. Manejo de errores y salida
- Mostrar errores con perror o mensajes consistentes.
- Si parseo falla, no ejecutar nada.
- Mantener exit_status actualizado.
Explicacion en defensa:
- Un shell robusto evita ejecutar comandos parcialmente parseados.
- exit_status es clave para $?.
---
## 12. Checklist para defensa (guion rapido)
1. Explico el flujo completo: lectura -> lexer -> parser -> expansion -> exec.
2. Explico como manejo comillas y metacaracteres.
3. Explico como construyo argv y redirecciones.
4. Explico expansion de $VAR y $?.
5. Explico pipes y redirecciones con dup2.
6. Explico por que los builtins se ejecutan en parent o child.
7. Explico manejo de senales y la variable global unica.
8. Explico exit_status y comportamiento de $?.
---
## 13. Sugerencia de estructura de archivos
- include/
- minishell.h
- core.h (estructuras globales y estado)
- parser.h (tokens, parser)
- executor.h
- builtins.h
- src/
- core/ (init, signals, util)
- parser/ (lexer.c, parser.c, expand.c)
- executor/ (executor.c, redirs.c)
- builtins/ (echo, cd, pwd, exit, env, export, unset)
- variables/ (environment.c)
- minishell.c (loop principal)
- main.c
Esto es solo una guia; no es obligatorio seguirla al pie de la letra.
---
## 14. Consejos para la defensa
- Usa bash como referencia de comportamiento.
- Demuestra un par de ejemplos: pipe, redireccion y expansion.
- Si algo falla, explica que el parser previene ejecucion parcial.
- Recalca el manejo correcto de ctrl-C y ctrl-\.