# 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-\.

