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

5.7 KiB

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.