6 Commits

Author SHA1 Message Date
marcnava-42cursus
ba40670ace Fixed variable expansion errors 2026-02-14 13:33:44 +01:00
marcnava-42cursus
dd6101edec A POR TODAAS 2026-02-14 06:14:59 +01:00
e2b734cf0c save commit 2026-02-14 05:48:18 +01:00
32b3bd72b5 fix: prompt was not being requested to hashmap 2026-02-14 02:05:49 +01:00
c95703b42b update: replaced set_env by set_var in export builtin 2026-02-14 02:02:52 +01:00
f4cfae1107 feat: added internal variables 2026-02-14 02:01:10 +01:00
26 changed files with 28571 additions and 262 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,26 @@
Tests eliminados del reporte por ser extras (\ y/o ~):
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/0_compare_parsing.sh:52 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/0_compare_parsing.sh:54 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/0_compare_parsing.sh:56 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/0_compare_parsing.sh:58 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/0_compare_parsing.sh:60 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/0_compare_parsing.sh:62 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/0_compare_parsing.sh:64 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:7 | motivo: ~
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:59 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:61 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:63 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:65 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:67 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:69 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:71 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:314 | motivo: ~
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:328 | motivo: ~
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:337 | motivo: ~
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:606 | motivo: \, ~
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_redirs.sh:208 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/2_path_check.sh:30 | motivo: ~
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/8_syntax_errors.sh:19 | motivo: ~
Total casos eliminados (extras): 22

View File

@@ -0,0 +1,59 @@
Tests eliminados del reporte por estar fuera del obligatorio:
- \ (barra invertida no especificada)
- ~ (tilde expansion no obligatoria)
- $"..." (extension bash, no requerida)
- ; (separador no obligatorio segun subject)
- && / || (bonus)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/0_compare_parsing.sh:26 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/0_compare_parsing.sh:28 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/0_compare_parsing.sh:32 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/0_compare_parsing.sh:34 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/0_compare_parsing.sh:52 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/0_compare_parsing.sh:54 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/0_compare_parsing.sh:56 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/0_compare_parsing.sh:58 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/0_compare_parsing.sh:60 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/0_compare_parsing.sh:62 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/0_compare_parsing.sh:64 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/10_parsing_hell.sh:301 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:7 | motivo: ~
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:31 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:33 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:37 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:39 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:59 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:61 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:63 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:65 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:67 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:69 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:71 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:314 | motivo: ~
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:328 | motivo: ~
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:337 | motivo: ~
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:536 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:538 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:552 | motivo: ; (no obligatorio)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_builtins.sh:606 | motivo: \, ~
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_redirs.sh:208 | motivo: \
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_variables.sh:40 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_variables.sh:42 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_variables.sh:44 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_variables.sh:48 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_variables.sh:60 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/1_variables.sh:62 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/2_correction.sh:129 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/2_correction.sh:139 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/2_correction.sh:141 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/2_correction.sh:143 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/2_correction.sh:147 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/2_correction.sh:159 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/2_correction.sh:161 | motivo: $"..." (bash extension)
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/2_path_check.sh:30 | motivo: ~
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/8_syntax_errors.sh:19 | motivo: ~
- /home/marcos/programming/minishell_sergio/tests/42_minishell_tester/cmds/mand/8_syntax_errors.sh:68 | motivo: &&/|| (bonus)
Total casos evaluados en reporte original: 195
Total casos eliminados (extras): 48
Total casos restantes (mandatory): 147

View File

@@ -6,7 +6,7 @@
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */ /* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/10/29 22:09:51 by sede-san #+# #+# */ /* Created: 2025/10/29 22:09:51 by sede-san #+# #+# */
/* Updated: 2026/02/08 19:42:50 by sede-san ### ########.fr */ /* Updated: 2026/02/14 01:15:34 by sede-san ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -16,6 +16,7 @@
# include "ft_args.h" # include "ft_args.h"
# include "minishell.h" # include "minishell.h"
# include "core.h" # include "core.h"
# include "variables.h"
typedef uint8_t (*t_builtin_func)(t_command cmd, t_minishell *minishell); typedef uint8_t (*t_builtin_func)(t_command cmd, t_minishell *minishell);

View File

@@ -6,7 +6,7 @@
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */ /* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/10/22 19:10:13 by sede-san #+# #+# */ /* Created: 2025/10/22 19:10:13 by sede-san #+# #+# */
/* Updated: 2026/02/13 20:06:08 by sede-san ### ########.fr */ /* Updated: 2026/02/14 01:25:43 by sede-san ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -63,15 +63,9 @@ typedef struct s_redirection
typedef struct s_variables typedef struct s_variables
{ {
t_hashmap *environment; t_hashmap *environment;
// char **internal; t_hashmap *internal;
} t_variables; } t_variables;
typedef struct s_prompt
{
const char *ps1; // primary prompt string
const char *ps2; // secondary prompt string for multiline input
} t_prompt;
/** /**
* @brief Main minishell structure containing global state information * @brief Main minishell structure containing global state information
* *
@@ -84,7 +78,6 @@ typedef struct s_minishell
{ {
t_variables variables; t_variables variables;
t_hashmap *builtins; t_hashmap *builtins;
t_prompt prompt;
uint8_t exit_status; uint8_t exit_status;
bool exit; bool exit;
} t_minishell; } t_minishell;
@@ -149,8 +142,8 @@ extern char **get_envp(t_minishell *msh);
extern void free_envp(char **envp); extern void free_envp(char **envp);
extern char *get_env(const char *env_name, t_minishell *msh); void handle_sigint_status(t_minishell *minishell);
bool handle_eof(char *line, t_minishell *minishell);
extern void unset_env(const char *env_name, t_minishell *msh);
#endif /* CORE_H */ #endif /* CORE_H */

View File

@@ -6,7 +6,7 @@
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */ /* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2026/02/10 22:28:01 by sede-san #+# #+# */ /* Created: 2026/02/10 22:28:01 by sede-san #+# #+# */
/* Updated: 2026/02/10 23:24:16 by sede-san ### ########.fr */ /* Updated: 2026/02/14 01:11:38 by sede-san ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -19,5 +19,6 @@
extern void syntax_error_unexpected_token(t_token *token); extern void syntax_error_unexpected_token(t_token *token);
extern void malloc_error(void); extern void malloc_error(void);
extern void command_not_found_error(const char *command);
#endif /* ERRORS_H */ #endif /* ERRORS_H */

View File

@@ -6,7 +6,7 @@
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */ /* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/10/20 16:35:10 by sede-san #+# #+# */ /* Created: 2025/10/20 16:35:10 by sede-san #+# #+# */
/* Updated: 2026/02/13 20:12:25 by sede-san ### ########.fr */ /* Updated: 2026/02/14 01:13:42 by sede-san ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -42,7 +42,4 @@
# include <term.h> // tgetent(3), tgetflag(3), tgetnum(3), # include <term.h> // tgetent(3), tgetflag(3), tgetnum(3),
// tgetstr(3), tgoto(3), tputs(3) // tgetstr(3), tgoto(3), tputs(3)
void handle_sigint_status(t_minishell *minishell);
bool handle_eof(char *line, t_minishell *minishell);
#endif /* MINISHELL_H */ #endif /* MINISHELL_H */

43
include/variables.h Normal file
View File

@@ -0,0 +1,43 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* variables.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2026/02/13 21:45:35 by sede-san #+# #+# */
/* Updated: 2026/02/14 01:24:49 by sede-san ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef VARIABLES_H
# define VARIABLES_H
# include "minishell.h"
# include "core.h"
// variables.c
extern char *get_var(const char *name, t_minishell *minishell);
extern void set_var(const char *name, char *value, t_minishell *minishell);
extern void unset_var(const char *name, t_minishell *minishell);
// environment.c
extern char *get_env(const char *name, t_minishell *minishell);
extern void set_env(const char *name, char *value, t_minishell *minishell);
extern void unset_env(const char *name, t_minishell *minishell);
extern void set_envp(char **envp, t_minishell *minishell);
extern char **get_envp(t_minishell *minishell);
extern void free_envp(char **envp);
// internal.c
extern char *get_int(const char *name, t_minishell *minishell);
extern void set_int(const char *name, char *value, t_minishell *minishell);
extern void unset_int(const char *name, t_minishell *minishell);
extern void set_intp(t_minishell *minishell);
#endif /* VARIABLES_H */

View File

@@ -6,7 +6,7 @@
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */ /* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2026/02/09 22:05:00 by codex #+# #+# */ /* Created: 2026/02/09 22:05:00 by codex #+# #+# */
/* Updated: 2026/02/09 22:05:00 by codex ### ########.fr */ /* Updated: 2026/02/14 02:02:14 by sede-san ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -71,9 +71,9 @@ static uint8_t export_one(
if (name == NULL) if (name == NULL)
return (EXIT_FAILURE); return (EXIT_FAILURE);
if (eq_pos != NULL) if (eq_pos != NULL)
set_env(name, eq_pos + 1, msh); set_var(name, eq_pos + 1, msh);
else else
set_env(name, "", msh); set_var(name, "", msh);
free(name); free(name);
return (EXIT_SUCCESS); return (EXIT_SUCCESS);
} }

View File

@@ -6,7 +6,7 @@
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */ /* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2026/02/11 00:00:00 by sede-san #+# #+# */ /* Created: 2026/02/11 00:00:00 by sede-san #+# #+# */
/* Updated: 2026/02/11 00:00:00 by sede-san ### ########.fr */ /* Updated: 2026/02/14 01:34:37 by sede-san ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -40,9 +40,13 @@ static void handle_execve_error(
) )
{ {
uint8_t exit_status; uint8_t exit_status;
size_t i;
exit_status = resolve_execve_status(); exit_status = resolve_execve_status();
free_envp(envp); i = 0;
while (envp[i] != NULL)
free(envp[i++]);
free(envp);
perror(command->path); perror(command->path);
exit(exit_status); exit(exit_status);
} }

View File

@@ -6,11 +6,12 @@
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */ /* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2026/02/11 00:00:00 by sede-san #+# #+# */ /* Created: 2026/02/11 00:00:00 by sede-san #+# #+# */
/* Updated: 2026/02/11 00:00:00 by sede-san ### ########.fr */ /* Updated: 2026/02/14 01:17:01 by sede-san ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "executor.h" #include "executor.h"
#include "variables.h"
static bool is_path_explicit( static bool is_path_explicit(
const char *command_name const char *command_name

View File

@@ -6,7 +6,7 @@
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */ /* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/10/20 20:51:33 by sede-san #+# #+# */ /* Created: 2025/10/20 20:51:33 by sede-san #+# #+# */
/* Updated: 2026/02/13 20:12:07 by sede-san ### ########.fr */ /* Updated: 2026/02/14 02:23:17 by sede-san ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -15,29 +15,22 @@
#include "parser.h" #include "parser.h"
#include "executor.h" #include "executor.h"
static void set_prompts(
t_minishell *minishell
)
{
minishell->prompt.ps1 = DEFAULT_PS1;
minishell->prompt.ps2 = DEFAULT_PS2;
}
void minishell_init( void minishell_init(
t_minishell *minishell, t_minishell *minishell,
char **envp char **envp
){ ){
ft_bzero(minishell, sizeof(t_minishell)); ft_bzero(minishell, sizeof(t_minishell));
set_intp(minishell);
set_envp(envp, minishell); set_envp(envp, minishell);
set_builtins(minishell); set_builtins(minishell);
set_prompts(minishell);
if (minishell->variables.environment == NULL || minishell->builtins == NULL) if (minishell->variables.environment == NULL || minishell->builtins == NULL)
minishell_clear(minishell); minishell_clear(minishell);
} }
void minishell_run( void minishell_run(
t_minishell *minishell t_minishell *minishell
){ )
{
char *line; char *line;
t_list *commands; t_list *commands;
@@ -47,7 +40,7 @@ void minishell_run(
while (!minishell->exit) while (!minishell->exit)
{ {
if (isatty(STDIN_FILENO)) if (isatty(STDIN_FILENO))
line = readline(minishell->prompt.ps1); line = readline(get_var("PS1", minishell));
else else
line = get_next_line(STDIN_FILENO); line = get_next_line(STDIN_FILENO);
handle_sigint_status(minishell); handle_sigint_status(minishell);
@@ -67,6 +60,8 @@ void minishell_clear(
t_minishell *minishell t_minishell *minishell
){ ){
rl_clear_history(); rl_clear_history();
if (minishell->variables.internal != NULL)
ft_hashmap_clear(&minishell->variables.internal, free);
if (minishell->variables.environment != NULL) if (minishell->variables.environment != NULL)
ft_hashmap_clear(&minishell->variables.environment, free); ft_hashmap_clear(&minishell->variables.environment, free);
if (minishell->builtins != NULL) if (minishell->builtins != NULL)

View File

@@ -6,92 +6,110 @@
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */ /* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2026/02/13 21:24:45 by sede-san #+# #+# */ /* Created: 2026/02/13 21:24:45 by sede-san #+# #+# */
/* Updated: 2026/02/13 21:24:45 by sede-san ### ########.fr */ /* Updated: 2026/02/14 06:56:00 by sede-san ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "parser.h" #include "parser_expand_internal.h"
#include "errors.h"
static char *replace_value(char *original, char *value, int start, int end); static void command_clear_argv_expand(
static void expand_variable(char **argument, int *i, t_minishell *minishell); t_command *command
static void expand_argument(char **argument, t_minishell *minishell);
static char *replace_value(
char *original,
char *value,
int start,
int end
) )
{ {
const char *before = ft_substr(original, 0, start);
const char *after = ft_substr(original, end, ft_strlen(original) - end);
const char *expanded = ft_strnjoin(3, before, value, after);
free((char *)before);
free((char *)after);
return ((char *)expanded);
}
static void expand_variable(
char **argument,
int *i,
t_minishell *minishell
)
{
char *expanded;
char *variable_name;
char *variable_value;
const int start = *i + 1;
int end;
end = start;
while (ft_isalnum((*argument)[end]) || (*argument)[end] == '_')
end++;
variable_name = ft_substr(*argument, start, end - start);
if (variable_name == NULL)
return (minishell->exit = true, malloc_error());
variable_value = get_env(variable_name, minishell);
free(variable_name);
if (variable_value == NULL)
variable_value = "";
expanded = replace_value(*argument, variable_value, start - 1, end);
if (expanded == NULL)
return (minishell->exit = true, malloc_error());
*i += ft_strlen(variable_value);
free(*argument);
*argument = expanded;
}
static void expand_argument(
char **argument,
t_minishell *minishell
)
{
bool in_single_quote;
bool in_double_quote;
int i; int i;
in_single_quote = false;
in_double_quote = false;
i = 0; i = 0;
while ((*argument)[i] != '\0') while (i < command->argc)
{ {
if ((*argument)[i] == '$' && !in_single_quote) free(command->argv[i]);
{
expand_variable(argument, &i, minishell);
if (*argument == NULL)
return (minishell->exit = true, malloc_error());
}
else
{
if ((*argument)[i] == '\'' && !in_double_quote)
in_single_quote = !in_single_quote;
else if ((*argument)[i] == '"' && !in_single_quote)
in_double_quote = !in_double_quote;
i++; i++;
} }
free(command->argv);
}
static bool command_set_expanded_argv(
t_command *command,
t_list *expanded_args,
t_minishell *minishell
)
{
char **argv;
t_list *current;
int argc;
int i;
argc = ft_lstsize(expanded_args);
argv = (char **)malloc(sizeof(char *) * (argc + 1));
if (argv == NULL)
return (ft_lstclear(&expanded_args, free),
parser_expand_malloc_error(minishell), false);
i = 0;
current = expanded_args;
while (current != NULL)
{
argv[i++] = (char *)current->content;
current = current->next;
} }
argv[i] = NULL;
ft_lstclear_nodes(&expanded_args);
command_clear_argv_expand(command);
command->argc = argc;
command->argv = argv;
return (true);
}
static bool expand_argv(
t_command *command,
t_minishell *minishell
)
{
int i;
t_list *expanded_args;
t_list *fields;
t_list *last;
i = 0;
expanded_args = NULL;
while (i < command->argc)
{
fields = NULL;
if (!parser_expand_word_fields(command->argv[i], minishell,
true, &fields))
return (ft_lstclear(&expanded_args, free), false);
if (expanded_args == NULL)
expanded_args = fields;
else
{
last = ft_lstlast(expanded_args);
if (last != NULL)
last->next = fields;
}
i++;
}
return (command_set_expanded_argv(command, expanded_args, minishell));
}
static bool expand_redirections(
t_list *redirections,
t_minishell *minishell,
bool expand_vars
)
{
t_redirection *redirection;
char *expanded;
while (redirections != NULL)
{
redirection = (t_redirection *)redirections->content;
expanded = parser_expand_word(redirection->target, minishell,
expand_vars);
if (expanded == NULL)
return (false);
free(redirection->target);
redirection->target = expanded;
redirections = redirections->next;
}
return (true);
} }
void expand( void expand(
@@ -99,24 +117,23 @@ void expand(
t_minishell *minishell t_minishell *minishell
) )
{ {
t_list *current_command; t_list *current;
t_command *command; t_command *command;
int i;
current_command = *commands; if (commands == NULL || *commands == NULL)
while (current_command != NULL) return ;
current = *commands;
while (current != NULL)
{ {
command = (t_command *)current_command->content; command = (t_command *)current->content;
i = 0; if (!expand_argv(command, minishell)
while (i < command->argc) || !expand_redirections(command->redirections, minishell, true)
|| !expand_redirections(command->heredocs, minishell, false))
{ {
expand_argument(&command->argv[i], minishell);
if (command->argv[i] == NULL)
ft_lstclear(commands, (void (*)(void *))command_clear); ft_lstclear(commands, (void (*)(void *))command_clear);
i++; *commands = NULL;
return ;
} }
if (command == NULL) current = current->next;
return (ft_lstclear(commands, (void (*)(void *))command_clear));
current_command = current_command->next;
} }
} }

View File

@@ -0,0 +1,90 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* parser_expand_fields.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2026/02/14 13:15:00 by sede-san #+# #+# */
/* Updated: 2026/02/14 13:15:00 by sede-san ### ########.fr */
/* */
/* ************************************************************************** */
#include "parser_expand_internal.h"
static t_fields_ctx init_fields_ctx(
t_list **fields,
char **current,
t_field_state *state
)
{
t_fields_ctx ctx;
ctx.fields = fields;
ctx.current = current;
ctx.touched = &state->touched;
ctx.in_single_quote = &state->in_single_quote;
ctx.in_double_quote = &state->in_double_quote;
return (ctx);
}
static bool finish_word_fields(
t_fields_ctx ctx
)
{
if (*ctx.in_single_quote || *ctx.in_double_quote)
{
ft_lstclear(ctx.fields, free);
free(*ctx.current);
syntax_error_unexpected_token(NULL);
ctx.minishell->exit_status = 2;
return (false);
}
if ((*ctx.touched || (*ctx.current)[0] != '\0')
&& !parser_fields_push_field(ctx))
return (false);
free(*ctx.current);
return (true);
}
static bool process_word_fields(
const char *word,
t_fields_ctx ctx
)
{
size_t i;
i = 0;
while (word[i] != '\0')
{
if (!parser_fields_step(word, &i, ctx))
return (false);
}
return (true);
}
bool parser_expand_word_fields(
const char *word,
t_minishell *minishell,
bool expand_vars,
t_list **fields
)
{
char *current;
t_field_state state;
t_fields_ctx ctx;
*fields = NULL;
current = ft_strdup("");
if (current == NULL)
return (parser_expand_malloc_error(minishell), false);
state.touched = false;
state.in_single_quote = false;
state.in_double_quote = false;
ctx = init_fields_ctx(fields, &current, &state);
ctx.minishell = minishell;
ctx.expand_vars = expand_vars;
if (!process_word_fields(word, ctx))
return (ft_lstclear(fields, free), free(current), false);
return (finish_word_fields(ctx));
}

View File

@@ -0,0 +1,105 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* parser_expand_fields_step.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2026/02/14 14:12:00 by sede-san #+# #+# */
/* Updated: 2026/02/14 14:12:00 by sede-san ### ########.fr */
/* */
/* ************************************************************************** */
#include "parser_expand_internal.h"
static bool handle_quote_char(
const char *word,
size_t *i,
t_fields_ctx ctx
)
{
if (word[*i] == '\'' && !*ctx.in_double_quote)
{
*ctx.in_single_quote = !*ctx.in_single_quote;
*ctx.touched = true;
(*i)++;
return (true);
}
if (word[*i] == '\"' && !*ctx.in_single_quote)
{
*ctx.in_double_quote = !*ctx.in_double_quote;
*ctx.touched = true;
(*i)++;
return (true);
}
return (false);
}
static bool skip_dollar_quote_prefix(
const char *word,
size_t *i,
t_fields_ctx ctx
)
{
if (word[*i] == '$' && !*ctx.in_single_quote && !*ctx.in_double_quote
&& word[*i + 1] != '\0'
&& (word[*i + 1] == '\'' || word[*i + 1] == '\"'))
{
(*i)++;
return (true);
}
return (false);
}
static bool expand_dollar_token(
const char *word,
size_t *i,
t_fields_ctx ctx,
bool *handled
)
{
char *expanded;
*handled = false;
if (word[*i] != '$' || *ctx.in_single_quote || !ctx.expand_vars)
return (true);
*handled = true;
expanded = parser_expand_variable(word, i, ctx.minishell);
if (expanded == NULL)
return (false);
if (!*ctx.in_double_quote
&& !parser_fields_expand_unquoted_value(ctx, expanded))
return (free(expanded), false);
if (*ctx.in_double_quote && !parser_fields_append_text(ctx.current,
expanded, ctx.minishell))
return (free(expanded), false);
if (*ctx.in_double_quote && expanded[0] != '\0')
*ctx.touched = true;
free(expanded);
return (true);
}
bool parser_fields_step(
const char *word,
size_t *i,
t_fields_ctx ctx
)
{
char value[2];
bool handled;
if (handle_quote_char(word, i, ctx))
return (true);
if (skip_dollar_quote_prefix(word, i, ctx))
return (true);
if (!expand_dollar_token(word, i, ctx, &handled))
return (false);
if (handled)
return (true);
value[0] = word[(*i)++];
value[1] = '\0';
if (!parser_fields_append_text(ctx.current, value, ctx.minishell))
return (false);
*ctx.touched = true;
return (true);
}

View File

@@ -0,0 +1,100 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* parser_expand_fields_utils.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2026/02/14 14:12:00 by sede-san #+# #+# */
/* Updated: 2026/02/14 14:12:00 by sede-san ### ########.fr */
/* */
/* ************************************************************************** */
#include "parser_expand_internal.h"
bool parser_fields_append_text(
char **current,
const char *value,
t_minishell *minishell
)
{
char *joined;
joined = ft_strnjoin(2, *current, (char *)value);
if (joined == NULL)
{
free(*current);
*current = NULL;
return (parser_expand_malloc_error(minishell), false);
}
free(*current);
*current = joined;
return (true);
}
static bool is_ifs_char(
char c
)
{
return (c == ' ' || c == '\t' || c == '\n');
}
bool parser_fields_push_field(
t_fields_ctx ctx
)
{
t_list *node;
node = ft_lstnew(*ctx.current);
if (node == NULL)
{
free(*ctx.current);
*ctx.current = NULL;
return (parser_expand_malloc_error(ctx.minishell), false);
}
ft_lstadd_back(ctx.fields, node);
*ctx.current = ft_strdup("");
if (*ctx.current == NULL)
return (ft_lstclear(ctx.fields, free),
parser_expand_malloc_error(ctx.minishell), false);
*ctx.touched = false;
return (true);
}
static void skip_ifs(
const char *expanded,
size_t *i
)
{
while (expanded[*i] != '\0' && is_ifs_char(expanded[*i]))
(*i)++;
}
bool parser_fields_expand_unquoted_value(
t_fields_ctx ctx,
const char *expanded
)
{
size_t i;
char value[2];
i = 0;
while (expanded[i] != '\0')
{
if (is_ifs_char(expanded[i]))
{
if ((*ctx.touched || (*ctx.current)[0] != '\0')
&& !parser_fields_push_field(ctx))
return (false);
skip_ifs(expanded, &i);
continue ;
}
value[0] = expanded[i];
value[1] = '\0';
if (!parser_fields_append_text(ctx.current, value, ctx.minishell))
return (false);
*ctx.touched = true;
i++;
}
return (true);
}

View File

@@ -0,0 +1,63 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* parser_expand_internal.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2026/02/14 06:56:00 by sede-san #+# #+# */
/* Updated: 2026/02/14 06:56:00 by sede-san ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef PARSER_EXPAND_INTERNAL_H
# define PARSER_EXPAND_INTERNAL_H
# include "parser.h"
# include "errors.h"
# include "variables.h"
typedef struct s_fields_ctx t_fields_ctx;
void parser_expand_malloc_error(t_minishell *minishell);
char *parser_expand_variable(const char *word, size_t *i,
t_minishell *minishell);
char *parser_expand_word(const char *word, t_minishell *minishell,
bool expand_vars);
bool parser_expand_word_fields(const char *word, t_minishell *minishell,
bool expand_vars, t_list **fields);
bool parser_fields_append_text(char **current, const char *value,
t_minishell *minishell);
bool parser_fields_push_field(t_fields_ctx ctx);
bool parser_fields_expand_unquoted_value(t_fields_ctx ctx,
const char *expanded);
bool parser_fields_step(const char *word, size_t *i, t_fields_ctx ctx);
typedef struct s_word_ctx
{
char **result;
bool *in_single_quote;
bool *in_double_quote;
t_minishell *minishell;
bool expand_vars;
} t_word_ctx;
typedef struct s_fields_ctx
{
t_list **fields;
char **current;
bool *touched;
bool *in_single_quote;
bool *in_double_quote;
t_minishell *minishell;
bool expand_vars;
} t_fields_ctx;
typedef struct s_field_state
{
bool touched;
bool in_single_quote;
bool in_double_quote;
} t_field_state;
#endif

View File

@@ -0,0 +1,82 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* parser_expand_variable.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2026/02/14 06:56:00 by sede-san #+# #+# */
/* Updated: 2026/02/14 06:56:00 by sede-san ### ########.fr */
/* */
/* ************************************************************************** */
#include "parser_expand_internal.h"
void parser_expand_malloc_error(
t_minishell *minishell
)
{
minishell->exit = true;
malloc_error();
}
static bool is_var_char(
char c
)
{
return (ft_isalnum(c) || c == '_');
}
static char *dup_or_error(
const char *value,
t_minishell *minishell
)
{
char *dup;
dup = ft_strdup(value);
if (dup == NULL)
return (parser_expand_malloc_error(minishell), NULL);
return (dup);
}
static char *expand_named_variable(
const char *word,
size_t *i,
t_minishell *minishell
)
{
char *name;
char *value;
size_t start;
start = *i;
while (word[*i] != '\0' && is_var_char(word[*i]))
(*i)++;
name = ft_substr(word, start, *i - start);
if (name == NULL)
return (parser_expand_malloc_error(minishell), NULL);
value = get_var(name, minishell);
free(name);
if (value == NULL)
value = "";
return (dup_or_error(value, minishell));
}
char *parser_expand_variable(const char *word, size_t *i,
t_minishell *minishell)
{
char *expanded;
(*i)++;
if (word[*i] == '?')
{
expanded = ft_itoa(minishell->exit_status);
if (expanded == NULL)
return (parser_expand_malloc_error(minishell), NULL);
return ((*i)++, expanded);
}
if (word[*i] == '\0' || !is_var_char(word[*i]))
return (dup_or_error("$", minishell));
return (expand_named_variable(word, i, minishell));
}

View File

@@ -0,0 +1,104 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* parser_expand_word.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2026/02/14 06:56:00 by sede-san #+# #+# */
/* Updated: 2026/02/14 06:56:00 by sede-san ### ########.fr */
/* */
/* ************************************************************************** */
#include "parser_expand_internal.h"
static bool word_toggle_quotes(
char c,
bool *in_single_quote,
bool *in_double_quote
)
{
if (c == '\'' && !*in_double_quote)
return (*in_single_quote = !*in_single_quote, true);
if (c == '\"' && !*in_single_quote)
return (*in_double_quote = !*in_double_quote, true);
return (false);
}
static bool word_append(
char **result,
const char *value,
t_minishell *minishell
)
{
char *joined;
joined = ft_strnjoin(2, *result, (char *)value);
if (joined == NULL)
{
free(*result);
*result = NULL;
return (parser_expand_malloc_error(minishell), false);
}
free(*result);
*result = joined;
return (true);
}
static bool word_step(
const char *word,
size_t *i,
t_word_ctx ctx
)
{
char *expanded;
char value[2];
if (word_toggle_quotes(word[*i], ctx.in_single_quote, ctx.in_double_quote))
return ((*i)++, true);
if (word[*i] == '$' && word[*i + 1] != '\0'
&& !*ctx.in_single_quote && !*ctx.in_double_quote
&& (word[*i + 1] == '\'' || word[*i + 1] == '\"'))
return ((*i)++, true);
if (word[*i] == '$' && !*ctx.in_single_quote && ctx.expand_vars)
{
expanded = parser_expand_variable(word, i, ctx.minishell);
if (expanded == NULL || !word_append(ctx.result, expanded,
ctx.minishell))
return (free(expanded), false);
return (free(expanded), true);
}
value[0] = word[*i];
value[1] = '\0';
(*i)++;
return (word_append(ctx.result, value, ctx.minishell));
}
char *parser_expand_word(
const char *word,
t_minishell *minishell,
bool expand_vars
)
{
char *result;
size_t i;
bool in_single_quote;
bool in_double_quote;
result = ft_strdup("");
if (result == NULL)
return (parser_expand_malloc_error(minishell), NULL);
i = 0;
in_single_quote = false;
in_double_quote = false;
while (word[i] != '\0')
{
if (!word_step(word, &i, (t_word_ctx){&result, &in_single_quote,
&in_double_quote, minishell, expand_vars}))
return (NULL);
}
if (in_single_quote || in_double_quote)
return (free(result), syntax_error_unexpected_token(NULL),
minishell->exit_status = 2, NULL);
return (result);
}

View File

@@ -6,7 +6,7 @@
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */ /* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2026/02/13 21:29:44 by sede-san #+# #+# */ /* Created: 2026/02/13 21:29:44 by sede-san #+# #+# */
/* Updated: 2026/02/13 21:29:44 by sede-san ### ########.fr */ /* Updated: 2026/02/14 03:34:38 by sede-san ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */

View File

@@ -6,65 +6,33 @@
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */ /* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/12/01 09:12:39 by sede-san #+# #+# */ /* Created: 2025/12/01 09:12:39 by sede-san #+# #+# */
/* Updated: 2026/02/08 19:44:15 by sede-san ### ########.fr */ /* Updated: 2026/02/14 01:32:42 by sede-san ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "minishell.h" #include "minishell.h"
#include "core.h" #include "core.h"
#include "variables.h"
#include "errors.h"
/** /**
* @brief Parses and stores environment variables from envp array into a hashmap * @brief Retrieves the value of an environment variable from the shell's
* environment hashmap.
* *
* This function iterates through the environment variables array (envp) and * This function searches for the specified environment variable name in the
* splits each variable string on the '=' delimiter to separate the variable * minishell's environment variable hashmap and returns its associated value.
* name from its value. Each name-value pair is then stored in the minishell's
* environment hashmap for later retrieval.
* *
* @param envp Array of environment variable strings in "NAME=value" format * @param name The name of the environment variable to retrieve.
* @param msh Pointer to the minishell structure containing the environment * @param minishell Pointer to the minishell object.
* hashmap
* *
* @note The function assumes envp strings are in the standard format * @return The value of the environment variable if found, NULL if not found
* "NAME=value"
*/ */
void set_envp( char *get_env(
char **envp, const char *name,
t_minishell *msh t_minishell *minishell
) { )
char *equal_sign; {
char *key; return (ft_hashmap_get(minishell->variables.environment, name));
char *value;
if (msh == NULL || envp == NULL)
return ;
msh->variables.environment
= ft_hashmap_new(32, ft_hashmap_hashstr, ft_hashmap_strcmp);
if (msh->variables.environment == NULL)
return ;
while (*envp != NULL)
{
equal_sign = ft_strchr(*envp, '=');
if (equal_sign == NULL)
{
key = ft_strdup(*envp);
value = ft_strdup("");
}
else
{
key = ft_substr(*envp, 0, equal_sign - *envp);
value = ft_strdup(equal_sign + 1);
}
if (key == NULL || value == NULL)
{
free(key);
free(value);
ft_hashmap_clear(&msh->variables.environment, free);
return ;
}
ft_hashmap_put(msh->variables.environment, key, value);
envp++;
}
} }
/** /**
@@ -75,29 +43,74 @@ void set_envp(
* the old value is freed to prevent memory leaks. If the variable is new, * the old value is freed to prevent memory leaks. If the variable is new,
* a duplicate of the key name is created for storage. * a duplicate of the key name is created for storage.
* *
* @param env_name The name of the environment variable to set * @param name The name of the environment variable to set
* @param env_value The value to assign to the environment variable * @param value The value to assign to the environment variable
* @param msh Pointer to the minishell structure containing the * @param minishell Pointer to the minishell object.
* environment hashmap
*/ */
void set_env( void set_env(
const char *env_name, const char *name,
char *env_value, char *value,
t_minishell *msh t_minishell *minishell
) { )
{
t_hashmap *environment; t_hashmap *environment;
const char *key; char *key;
char *val;
char *old_value; char *old_value;
environment = msh->variables.environment; environment = minishell->variables.environment;
key = env_name; key = (char *)name;
if (!ft_hashmap_contains_key(environment, key)) if (key != NULL && !ft_hashmap_contains_key(environment, key))
key = ft_strdup(env_name); {
old_value = ft_hashmap_put(environment, key, ft_strdup(env_value)); key = ft_strdup(name);
if (key == NULL)
{
minishell->exit = true;
malloc_error();
return ;
}
}
val = value;
if (val == NULL)
val = ft_strdup("");
else
val = ft_strdup(value);
if (val == NULL)
{
if (key != name)
free(key);
minishell->exit = true;
malloc_error();
return ;
}
old_value = ft_hashmap_put(environment, key, val);
if (old_value != NULL) if (old_value != NULL)
free(old_value); free(old_value);
} }
/**
* @brief Removes an environment variable by name.
*
* @param name The name of the environment variable to remove.
* @param minishell Pointer to the minishell structure.
*
* @note If the environment variable exists, it will be removed from the hashmap
* and its associated value will be freed.
*/
void unset_env(
const char *name,
t_minishell *minishell
)
{
t_hashmap *environment;
char *val;
environment = minishell->variables.environment;
val = ft_hashmap_remove(environment, (void *)name);
if (val != NULL)
free(val);
}
/** /**
* @brief Converts the environment variables hashmap to an envp array format. * @brief Converts the environment variables hashmap to an envp array format.
* *
@@ -105,7 +118,7 @@ void set_env(
* environment hashmap and converts them into a NULL-terminated array of * environment hashmap and converts them into a NULL-terminated array of
* strings in the format "KEY=VALUE". * strings in the format "KEY=VALUE".
* *
* @param msh Pointer to the minishell structure containing the environment * @param minishell Pointer to the minishell structure containing the environment
* variables hashmap. * variables hashmap.
* *
* @return A dynamically allocated array of strings representing environment * @return A dynamically allocated array of strings representing environment
@@ -120,17 +133,18 @@ void set_env(
* the NULL terminator. * the NULL terminator.
*/ */
char **get_envp( char **get_envp(
t_minishell *msh t_minishell *minishell
) { )
{
char **envp; char **envp;
t_list *env_list; t_list *env_list;
t_list *env; t_list *env;
t_map_entry *entry; t_map_entry *entry;
size_t i; size_t i;
env_list = ft_hashmap_entries(msh->variables.environment); env_list = ft_hashmap_entries(minishell->variables.environment);
envp = (char **)malloc( envp = (char **)malloc(
(msh->variables.environment->size + 1) * sizeof(char *) (minishell->variables.environment->size + 1) * sizeof(char *)
); );
if (envp != NULL) if (envp != NULL)
{ {
@@ -149,44 +163,39 @@ char **get_envp(
} }
/** /**
* @brief Frees a dynamically allocated environment variables array * @brief Parses and stores environment variables from envp array into a hashmap
* *
* This function deallocates memory for an array of strings that was previously * This function iterates through the environment variables array (envp) and
* allocated by `get_envp()`. It iterates through each string in the array, * splits each variable string on the '=' delimiter to separate the variable
* frees the memory for individual strings, and then frees the array itself. * name from its value. Each name-value pair is then stored in the minishell's
* environment hashmap for later retrieval.
* *
* @param envp Pointer to the array of environment variable strings to be freed. * @param envp Array of environment variable strings in "NAME=value" format
* Each string in the array should be dynamically allocated. * @param minishell Pointer to the minishell structure containing the environment
* The array must be NULL-terminated. * hashmap
*
* @note The function assumes envp strings are in the standard format
* "NAME=value"
*/ */
void free_envp( void set_envp(
char **envp char **envp,
) { t_minishell *minishell
size_t i; )
{
t_hashmap **environment;
char **key_value;
i = -1; if (minishell == NULL || envp == NULL)
while (envp[++i] != NULL) return ;
free(envp[i]); environment = &minishell->variables.environment;
free(envp); *environment = ft_hashmap_new(32, ft_hashmap_hashstr, ft_hashmap_strcmp);
} if (*environment == NULL)
return ;
/** while (*envp != NULL)
* @brief Retrieves the value of an environment variable from the shell's {
* environment hashmap. key_value = ft_split(*envp, '=');
* set_env(key_value[0], key_value[1], minishell);
* This function searches for the specified environment variable name in the ft_free_split(key_value);
* minishell's environment variable hashmap and returns its associated value. envp++;
* }
* @param env_name The name of the environment variable to retrieve (e.g.,
* "PATH", "HOME")
* @param msh Pointer to the minishell structure containing the environment
* variables hashmap
*
* @return The value of the environment variable if found, NULL if not found
*/
char *get_env(
const char *env_name,
t_minishell *msh
) {
return (ft_hashmap_get(msh->variables.environment, env_name));
} }

View File

@@ -1,41 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* environment_unset.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2026/02/09 22:16:00 by codex #+# #+# */
/* Updated: 2026/02/09 22:16:00 by codex ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
#include "core.h"
void unset_env(
const char *env_name,
t_minishell *msh
){
t_hashmap *new_env;
t_list *entries;
t_list *current;
t_map_entry *entry;
new_env = ft_hashmap_new(32, ft_hashmap_hashstr, ft_hashmap_strcmp);
if (new_env == NULL)
return ;
entries = ft_hashmap_entries(msh->variables.environment);
current = entries;
while (current != NULL)
{
entry = current->content;
if (ft_strcmp(entry->key, env_name) != 0)
ft_hashmap_put(new_env,
ft_strdup(entry->key), ft_strdup(entry->value));
current = current->next;
}
ft_lstclear_nodes(&entries);
ft_hashmap_clear(&msh->variables.environment, free);
msh->variables.environment = new_env;
}

View File

@@ -0,0 +1,120 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* internal.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2026/02/13 21:29:43 by sede-san #+# #+# */
/* Updated: 2026/02/14 01:39:36 by sede-san ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
#include "core.h"
#include "errors.h"
/**
* @brief Retrieves the value of an internal variable by name.
*
* @param name The name of the internal variable to retrieve.
* @param minishell Pointer to the minishell structure.
*
* @return The value of the internal variable if found, or NULL if not found.
*/
char *get_int(
const char *name,
t_minishell *minishell
)
{
return (ft_hashmap_get(minishell->variables.internal, name));
}
/**
* @brief Stores a variable as internal.
*
* @param name The name of the internal variable to set.
* @param value The value to associate with the internal variable.
* @param minishell Pointer to the minishell structure.
*
* @note If the internal variable already exists, its value will be updated and
* the old value will be freed. If it does not exist, a new internal
* variable will be created.
*/
void set_int(
const char *name,
char *value,
t_minishell *minishell
)
{
t_hashmap *internal;
char *key;
char *val;
char *old_val;
internal = minishell->variables.internal;
key = (char *)name;
if (key != NULL && !ft_hashmap_contains_key(internal, key))
{
key = ft_strdup(name);
if (key == NULL)
return (minishell->exit = true, malloc_error());
}
val = value;
if (val != NULL)
val = ft_strdup(value);
if (val == NULL)
{
if (key != name)
free(key);
return (minishell->exit = true, malloc_error());
}
old_val = ft_hashmap_put(internal, key, val);
if (old_val != NULL)
free(old_val);
}
/**
* @brief Removes an internal variable by name.
*
* @param name The name of the internal variable to remove.
* @param minishell Pointer to the minishell structure.
*
* @note If the internal variable exists, it will be removed from the hashmap
* and its associated value will be freed.
*/
void unset_int(
const char *name,
t_minishell *minishell
)
{
char *value;
value = ft_hashmap_remove(minishell->variables.internal, (void *)name);
if (value != NULL)
free(value);
}
/**
* @brief Initializes the internal variables hashmap with default values.
*
* @param minishell Pointer to the minishell structure to initialize.
*
* @warning This function must be called only once during the initialization of
* the minishell.
*/
void set_intp(
t_minishell *minishell
)
{
if (minishell == NULL)
return ;
minishell->variables.internal
= ft_hashmap_new(16, ft_hashmap_hashstr, ft_hashmap_strcmp);
if (minishell->variables.internal == NULL)
return ;
set_int("?", "0", minishell);
set_int("_", "minishell", minishell);
set_int("PS1", DEFAULT_PS1, minishell);
set_int("PS2", DEFAULT_PS2, minishell);
}

50
src/variables/variables.c Normal file
View File

@@ -0,0 +1,50 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* variables.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2026/02/13 21:41:44 by sede-san #+# #+# */
/* Updated: 2026/02/14 00:52:12 by sede-san ### ########.fr */
/* */
/* ************************************************************************** */
#include "variables.h"
/**
* @brief Retrieves the value of a variable by name.
*
* @param name The name of the variable to retrieve.
* @param minishell Pointer to the minishell structure.
*
* @return The value of the variable if found, or NULL if not found.
*/
char *get_var(
const char *name,
t_minishell *minishell
)
{
char *value;
value = get_int(name, minishell);
if (value == NULL)
value = get_env(name, minishell);
return (value);
}
void set_var(const char *name, char *value, t_minishell *minishell)
{
if (ft_hashmap_contains_key(minishell->variables.internal, name))
set_int(name, value, minishell);
set_env(name, value, minishell);
}
void unset_var(
const char *name,
t_minishell *minishell
)
{
unset_int(name, minishell);
unset_env(name, minishell);
}