Compare commits
6 Commits
fix/builti
...
fix/variab
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ba40670ace | ||
|
|
dd6101edec | ||
| e2b734cf0c | |||
| 32b3bd72b5 | |||
| c95703b42b | |||
| f4cfae1107 |
9656
docs/mstest_m_failed_tests_report.txt
Normal file
9656
docs/mstest_m_failed_tests_report.txt
Normal file
File diff suppressed because it is too large
Load Diff
9178
docs/mstest_m_failed_tests_report_filtered.txt
Normal file
9178
docs/mstest_m_failed_tests_report_filtered.txt
Normal file
File diff suppressed because it is too large
Load Diff
8656
docs/mstest_m_failed_tests_report_mandatory_only.txt
Normal file
8656
docs/mstest_m_failed_tests_report_mandatory_only.txt
Normal file
File diff suppressed because it is too large
Load Diff
26
docs/mstest_m_removed_extra_tests.txt
Normal file
26
docs/mstest_m_removed_extra_tests.txt
Normal 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
|
||||||
59
docs/mstest_m_removed_extra_tests_mandatory_only.txt
Normal file
59
docs/mstest_m_removed_extra_tests_mandatory_only.txt
Normal 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
|
||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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 */
|
||||||
@@ -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
43
include/variables.h
Normal 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 */
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
90
src/parser/parser_expand_fields.c
Normal file
90
src/parser/parser_expand_fields.c
Normal 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, ¤t, &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));
|
||||||
|
}
|
||||||
105
src/parser/parser_expand_fields_step.c
Normal file
105
src/parser/parser_expand_fields_step.c
Normal 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);
|
||||||
|
}
|
||||||
100
src/parser/parser_expand_fields_utils.c
Normal file
100
src/parser/parser_expand_fields_utils.c
Normal 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);
|
||||||
|
}
|
||||||
63
src/parser/parser_expand_internal.h
Normal file
63
src/parser/parser_expand_internal.h
Normal 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
|
||||||
82
src/parser/parser_expand_variable.c
Normal file
82
src/parser/parser_expand_variable.c
Normal 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));
|
||||||
|
}
|
||||||
104
src/parser/parser_expand_word.c
Normal file
104
src/parser/parser_expand_word.c
Normal 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);
|
||||||
|
}
|
||||||
@@ -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 */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
|||||||
@@ -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));
|
|
||||||
}
|
}
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
120
src/variables/internal/internal.c
Normal file
120
src/variables/internal/internal.c
Normal 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
50
src/variables/variables.c
Normal 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);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user