Files
minishell/docs/builtins_fixes.md
marcnava-42cursus 778e0c0481 Builtins fixed
The builtins wasnt protected, now all data received is protected, the hashmap addition is protected and added functionality of env, export and unset (not implemented in this version). Added fixed details documentation in docs/builtins_fixes.md generated by codex and created tests/builtins_edge_cases.sh to test all the builtins to work correctly
2026-02-09 22:08:45 +01:00

152 lines
5.7 KiB
Markdown

# Correcciones en Builtins
Este documento resume los fallos detectados en los builtins actuales y la
solucion aplicada en codigo.
## 1) Infraestructura de builtins (`include/builtins.h`, `src/builtins/builtins.c`)
### Fallo
- Uso inconsistente de tipos (`u_int8_t`/`unsigned char` frente a `uint8_t`).
- `set_builtins` no comprobaba fallos de registro por builtin (duplicado de
clave o insercion en hashmap), pudiendo dejar estado parcial.
- `is_builtin` podia dereferenciar punteros nulos.
### Por que fallaba
- `u_int8_t` no es el tipo estandar C99 y depende de plataforma/headers.
- Si falla una insercion, la tabla quedaba inicializada parcialmente sin
rollback.
- En errores de inicializacion, consultar `is_builtin` podia romper.
### Solucion
- Unificacion de firmas a `uint8_t`.
- Nuevo helper `register_builtin()` con validacion tras `ft_hashmap_put`.
- Si falla cualquier alta: limpieza de `minishell->builtins` y retorno de
error.
- Guardas nulas en `is_builtin`.
## 2) `cd` (`src/builtins/cd/cd.c`)
### Fallo
- `cd` con demasiados argumentos devolvia `2` (bash devuelve `1`).
- `cd` sin `HOME` acababa llamando a `chdir(NULL)`.
- El manejo de error usaba comprobaciones invertidas (`access`) y codigos
incorrectos.
- No se actualizaban `PWD` y `OLDPWD` tras `chdir` exitoso.
- `cd -` (usar `OLDPWD`) no estaba soportado.
### Por que fallaba
- Codigos de salida incompatibles con el comportamiento esperado del shell.
- `HOME` no definido no se controlaba antes del `chdir`.
- La logica de `access` estaba al reves y mezclaba condiciones.
- Variables de entorno del directorio quedaban desincronizadas.
- Faltaba resolver el caso especial de `-` hacia `OLDPWD`.
### Solucion
- Refactor en `resolve_cd_path()` para validar argumentos y `HOME`.
- Retorno `EXIT_FAILURE` en `too many arguments` y `HOME not set`.
- Error de `chdir` simplificado a `perror("minishell: cd")` + retorno `1`.
- Actualizacion de `OLDPWD` y `PWD` mediante `getcwd(NULL, 0)` + `set_env()`.
- Soporte de `cd -`: usa `OLDPWD`, valida `OLDPWD not set` e imprime el nuevo
directorio tras el cambio.
## 3) `exit` (`src/builtins/exit/exit.c`)
### Fallo
- Habia un `printf` de debug en ejecucion real.
- `exit <no_numerico>` devolvia `2` pero no cerraba el shell.
- `exit n m` devolvia `2`; en bash es `1` y no sale del shell.
- Validacion numerica basada en `ft_strisnum` sin control de overflow.
- Se mostraba `exit` incluso en contexto no interactivo.
### Por que fallaba
- Debug residual contamina salida.
- Semantica de `exit` incompleta respecto a bash.
- Valores fuera de rango podian tratarse como validos por conversion directa.
- Mensaje `exit` debe mostrarse solo en shell interactivo.
### Solucion
- Eliminado debug print.
- Nuevo flujo `resolve_exit_status()`:
- Sin argumentos: usa `msh->exit_status`.
- Argumento no numerico o fuera de `long`: mensaje
`numeric argument required`, `msh->exit = true`, estado `2`.
- Demasiados argumentos: mensaje de error y estado `1`, sin salir.
- Parser numerico propio (`get_uint8_from_num` + `has_overflow`) con soporte
de signo y control de overflow.
- `ft_eputendl("exit")` solo si `isatty(STDIN_FILENO)`.
## 4) `pwd` (`src/builtins/pwd/pwd.c`)
### Fallo
- Si `getcwd` fallaba, el builtin devolvia `EXIT_SUCCESS`.
- Uso de buffer fijo (`PATH_MAX`) menos robusto para rutas largas.
### Por que fallaba
- El shell reportaba exito aunque no pudiera obtener el directorio.
- Un buffer fijo puede truncar o fallar en escenarios de rutas profundas.
### Solucion
- Cambio a `getcwd(NULL, 0)` con memoria dinamica.
- Si falla, `perror("minishell: pwd")` y retorno `EXIT_FAILURE`.
- `free()` del buffer dinamico tras imprimir.
## 5) `echo` (`src/builtins/echo/echo.c`, `src/builtins/echo/echo_def.c`)
### Cambio aplicado
- Ajuste de tipos de retorno auxiliares a `uint8_t` para mantener consistencia
con `builtins.h`.
### Nota
- No se detectaron fallos funcionales criticos adicionales en la logica actual
de `echo` durante esta revision.
## 6) Builtins faltantes: `env`, `export`, `unset`
### Fallo
- Los builtins `env`, `export` y `unset` no estaban implementados ni
registrados en `set_builtins`.
### Por que fallaba
- Comandos basicos de shell no existian en la tabla de builtins.
- Cualquier prueba/flujo que dependiera de gestion de variables exportadas
fallaba (listar, crear y eliminar variables de entorno).
### Solucion
- Nuevos builtins implementados:
- `src/builtins/env/env.c`
- `src/builtins/export/export.c`
- `src/builtins/unset/unset.c`
- Registro en `src/builtins/builtins.c` (tabla ampliada de 4 a 7 entradas).
- Nuevos prototipos en `include/builtins.h`.
- Soporte de borrado real de entorno mediante `unset_env`:
- Declaracion en `include/core.h`
- Implementacion en `src/variables/environment_unset.c`
## 7) Comportamiento aplicado en los nuevos builtins
### `env`
- Si recibe argumentos, devuelve error (`minishell: env: too many arguments`)
y estado `1`.
- Sin argumentos, lista `KEY=VALUE` de las variables de entorno actuales.
### `export`
- `export NAME=VALUE`: crea/actualiza la variable.
- `export NAME`: crea/actualiza con valor vacio (`NAME=`) para que aparezca
en `env`.
- Identificadores invalidos (`1A=2`, etc.) devuelven error
`not a valid identifier` y estado `1`.
- Sin argumentos, reutiliza el listado de `env`.
### `unset`
- Elimina variables validas del entorno en memoria.
- Identificadores invalidos devuelven error
`not a valid identifier` y estado `1`.
- Si el identificador es valido y no existe, no falla (comportamiento shell).
## Validacion realizada
- `norminette` ejecutado sobre los archivos modificados: `OK`.
- Build completa no ejecutable en este entorno por falta de acceso de red al
clonado de librerias (`github.com`), por lo que no se pudo validar runtime
del binario en esta sesion.