save commit

This commit is contained in:
2026-02-09 20:47:43 +01:00
parent e983f7fe64
commit 280fa51f94
39 changed files with 3400 additions and 239 deletions

View File

@@ -6,28 +6,29 @@
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/12/01 17:04:57 by sede-san #+# #+# */
/* Updated: 2025/12/01 17:54:26 by sede-san ### ########.fr */
/* Updated: 2026/02/08 19:51:38 by sede-san ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
#include "builtins.h"
u_int8_t set_builtins(
t_minishell *msh
t_minishell *minishell
) {
msh->builtins = ft_hashmap_new(4, ft_hashmap_hashstr, ft_hashmap_strcmp);
if (msh->builtins == NULL)
minishell->builtins
= ft_hashmap_new(4, ft_hashmap_hashstr, ft_hashmap_strcmp);
if (minishell->builtins == NULL)
return (0);
ft_hashmap_put(msh->builtins, ft_strdup("cd"), builtin_cd);
ft_hashmap_put(msh->builtins, ft_strdup("echo"), builtin_echo);
ft_hashmap_put(msh->builtins, ft_strdup("exit"), builtin_exit);
ft_hashmap_put(msh->builtins, ft_strdup("pwd"), builtin_pwd);
ft_hashmap_put(minishell->builtins, ft_strdup("cd"), builtin_cd);
ft_hashmap_put(minishell->builtins, ft_strdup("echo"), builtin_echo);
ft_hashmap_put(minishell->builtins, ft_strdup("exit"), builtin_exit);
ft_hashmap_put(minishell->builtins, ft_strdup("pwd"), builtin_pwd);
return (1);
}
u_int8_t is_builtin(
const char *command_name,
t_minishell *msh
t_minishell *minishell
) {
return (ft_hashmap_contains_key(msh->builtins, command_name));
return (ft_hashmap_contains_key(minishell->builtins, command_name));
}

View File

@@ -6,28 +6,28 @@
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/10/30 01:20:48 by sede-san #+# #+# */
/* Updated: 2025/12/01 19:15:08 by sede-san ### ########.fr */
/* Updated: 2026/02/08 21:16:18 by sede-san ### ########.fr */
/* */
/* ************************************************************************** */
#include "builtins.h"
#include <stdint.h>
u_int8_t builtin_exit(
uint8_t builtin_exit(
t_command cmd,
t_minishell *msh
){
)
{
uint8_t exit_status;
ft_eputendl("exit");
if (cmd.argc == 1)
{
msh->exit = 1;
// return the last exit_status, if none 0 is returned
return (msh->exit_status);
}
exit_status = msh->exit_status;
else if (!ft_strisnum(cmd.argv[1]))
{
ft_eputstr("exit: ");
ft_eputendl(cmd.argv[1]);
ft_eputendl(": numeric argument required");
ft_eprintf(
"minishell: exit: %s: numeric argument required\n",
cmd.argv[1]);
return (2);
}
else if (cmd.argc > 2)
@@ -36,9 +36,11 @@ u_int8_t builtin_exit(
return (2);
}
else
{
msh->exit = 1;
// cast to u_int8_t causes to return a value between 0 and 255
return ((u_int8_t)ft_atol(cmd.argv[1]));
}
exit_status = (uint8_t)ft_atol(cmd.argv[1]);
printf("builtin_exit: exit_status=%d\n", exit_status); // Debug print
msh->exit = 1;
msh->exit_status = exit_status;
return (exit_status);
}

View File

@@ -0,0 +1,12 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* command.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2026/02/09 18:40:03 by sede-san #+# #+# */
/* Updated: 2026/02/09 18:40:04 by sede-san ### ########.fr */
/* */
/* ************************************************************************** */

View File

@@ -5,133 +5,226 @@
/* +:+ +:+ +:+ */
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/10/28 13:03:44 by sede-san #+# #+# */
/* Updated: 2025/12/02 09:07:28 by sede-san ### ########.fr */
/* Created: 2026/02/08 19:10:47 by sede-san #+# #+# */
/* Updated: 2026/02/08 21:32:03 by sede-san ### ########.fr */
/* */
/* ************************************************************************** */
#include "executor.h"
#include "builtins.h"
static char *solve_path(char *cmd_name, t_minishell *msh);
static u_int8_t path_is_solved(char *cmd_name, t_minishell *msh);
static void handle_child(t_command *cmd, t_minishell *msh);
static void handle_parent(pid_t child_pid, t_command *cmd, t_minishell *msh);
static inline uint8_t execute_builtin(
const t_command *command,
t_minishell *minishell
)
{
const t_builtin_func builtin
= ft_hashmap_get(minishell->builtins, command->path);
u_int8_t execute(
t_command cmd,
t_minishell *msh
) {
pid_t child_pid;
cmd.path = solve_path(cmd.argv[0], msh);
if (!cmd.path)
{
ft_eprintf("minishell: %s: command not found\n", cmd.argv[0]);
return (msh->exit_status = 127, msh->exit_status);
}
if (!is_builtin(cmd.path, msh) && access(cmd.path, X_OK) != EXIT_SUCCESS)
{
ft_eputstr("minishell: ");
perror(cmd.path);
return (msh->exit_status = 126, msh->exit_status);
}
child_pid = 0;
if (!is_builtin(cmd.path, msh))
child_pid = fork();
if (child_pid == -1)
perror("minishell");
else if (child_pid == 0)
handle_child(&cmd, msh);
else
handle_parent(child_pid, &cmd, msh);
return (msh->exit_status);
return (builtin(*command, minishell));
}
static char *solve_path(
char *cmd_name,
t_minishell *msh
){
char *cmd_path;
char **path;
static void handle_execve_error(
const t_command *command,
char **envp
)
{
free_envp(envp);
perror(command->path);
exit(EXIT_FAILURE);
}
static void execute_external_command(
const t_command *command,
t_minishell *minishell
)
{
char **envp;
envp = get_envp(minishell);
if (envp == NULL)
{
perror("get_envp");
exit(EXIT_FAILURE);
}
execve(command->path, command->argv, envp);
handle_execve_error(command, envp);
}
static uint8_t execute_command(
const t_command *command,
t_minishell *minishell
)
{
if (is_builtin(command->path, minishell))
return (execute_builtin(command, minishell));
else
{
execute_external_command(command, minishell);
return (EXIT_FAILURE); //! should never reach here
}
}
static void cmdfree_argv(
char **argv
)
{
size_t i;
if (path_is_solved(cmd_name, msh))
// return a copy to avoid double free on parent
return (ft_strdup(cmd_name));
path = ft_split(get_env("PATH", msh), COLON);
if (!path)
return (NULL);
cmd_path = NULL;
i = -1;
while (!cmd_path && path[++i])
if (argv == NULL)
return ;
i = 0;
while (argv[i] != NULL)
{
cmd_path = ft_strnjoin(3, path[i], "/", cmd_name);
if (!cmd_path)
return (NULL);
/**
* If a command exists but user has no execution permission
* the command is shown as non existant instead of showing the
* last ocurrence found
*
* TLDR: bash shows 'Permission denied'
* and minishell 'command not found'
*
* TEST: execute an existing command without permission to do so
*/
if (access(cmd_path, X_OK) != EXIT_SUCCESS)
ft_free((void **)&cmd_path);
free(argv[i]);
i++;
}
ft_free_split((char **)path);
if (!cmd_path)
return (NULL);
return (cmd_path);
free(argv);
}
static u_int8_t path_is_solved(
char *cmd_name,
t_minishell *msh
){
return (ft_strncmp(cmd_name, "/", 1) == 0
|| (cmd_name[1] && ft_strncmp(cmd_name, "./", 2) == 0)
|| (cmd_name[2] && ft_strncmp(cmd_name, "../", 3) == 0)
|| is_builtin(cmd_name, msh)
);
static void cmdfree(
t_command *command
)
{
if (command == NULL)
return ;
cmdfree_argv(command->argv);
free(command->path);
free(command);
}
static void handle_child(
t_command *cmd,
t_minishell *msh
){
char **envp;
t_builtin_func builtin;
static int create_pipe_if_needed(
t_list *current_command,
t_pipeline *pipeline
)
{
if (!current_command->next)
return (0);
if (pipe(pipeline->pipefd) == PIPE_ERROR)
return (perror("pipe"), PIPE_ERROR);
return (0);
}
if (is_builtin(cmd->argv[0], msh))
static bool is_fork_required(
t_list *current_command,
t_minishell *minishell
) {
const t_command *command = current_command->content;
return (current_command->next != NULL
|| !is_builtin(command->path, minishell));
}
static pid_t fork_process(
t_list *current_command,
t_minishell *minishell
)
{
pid_t pid;
pid = 0;
if (is_fork_required(current_command, minishell))
pid = fork();
if (pid == FORK_ERROR)
perror("fork");
return (pid);
}
static void setup_child_input(
t_pipeline *pipeline
)
{
if (pipeline->prev_read_fd != -1)
{
builtin = ft_hashmap_get(msh->builtins, cmd->argv[0]);
builtin(*cmd, msh);
dup2(pipeline->prev_read_fd, STDIN_FILENO);
close(pipeline->prev_read_fd);
}
}
static void setup_child_output(
t_list *current_command,
t_pipeline *pipeline
)
{
if (current_command->next)
{
dup2(pipeline->pipefd[WRITE_PIPE], STDOUT_FILENO);
close(pipeline->pipefd[READ_PIPE]);
close(pipeline->pipefd[WRITE_PIPE]);
}
}
static void child_process(
t_list *current_command,
t_pipeline *pipeline,
t_minishell *minishell
)
{
uint8_t exit_status;
const t_command *command = current_command->content;
setup_child_input(pipeline);
setup_child_output(current_command, pipeline);
exit_status = execute_command(command, minishell);
if (is_fork_required(current_command, minishell))
exit(exit_status);
}
static void parent_cleanup(
t_list *current_command,
t_pipeline *pipeline
)
{
if (pipeline->prev_read_fd != -1)
close(pipeline->prev_read_fd);
if (current_command->next)
{
close(pipeline->pipefd[WRITE_PIPE]);
pipeline->prev_read_fd = pipeline->pipefd[READ_PIPE];
}
else
{
envp = get_envp(msh);
execve(cmd->path, cmd->argv, envp);
free_envp(envp);
}
pipeline->prev_read_fd = -1;
}
static void handle_parent(
pid_t child_pid,
t_command *cmd,
t_minishell *msh
){
if (waitpid(child_pid, (int *)&msh->exit_status, 0) == EXIT_SUCCESS)
static uint8_t wait_for_children(void)
{
uint8_t exit_status;
int status;
exit_status = EXIT_SUCCESS;
while (wait(&status) > 0)
{
// handle success
if (WIFEXITED(status))
exit_status = WEXITSTATUS(status);
}
else
{
// handle error
}
ft_free((void **)&cmd->path);
ft_free_split(cmd->argv);
return (exit_status);
}
uint8_t execute(
t_list *command_list,
t_minishell *minishell
)
{
uint8_t exit_status;
t_pipeline pipeline;
t_list *current_command;
pid_t pid;
pipeline.prev_read_fd = -1;
current_command = command_list;
while (current_command)
{
if (create_pipe_if_needed(current_command, &pipeline) == PIPE_ERROR)
break ;
pid = fork_process(current_command, minishell);
if (pid == FORK_ERROR)
break ;
if (pid == 0)
child_process(current_command, &pipeline, minishell);
parent_cleanup(current_command, &pipeline);
current_command = current_command->next;
}
exit_status = wait_for_children();
ft_lstclear(&command_list, (void (*)(void *))cmdfree);
return (exit_status);
}

View File

@@ -3,14 +3,15 @@
/* ::: :::::::: */
/* main.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: padan-pe <padan-pe@student.42.fr> +#+ +:+ +#+ */
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/10/20 16:34:42 by sede-san #+# #+# */
/* Updated: 2025/10/23 17:10:17 by padan-pe ### ########.fr */
/* Updated: 2026/02/09 18:46:21 by sede-san ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
#include "core.h"
int main(
int argc,
@@ -18,19 +19,14 @@ int main(
char **envp
){
t_minishell minishell;
u_int8_t exit_status;
if (argc != 1 || argv[1] || !envp)
{
printf("Usage: ./minishell\n");
return (EXIT_FAILURE);
}
if (!minishell_init(&minishell, envp))
{
printf("Error: %s\n", "failed to initialize minishell");
return (EXIT_FAILURE);
}
exit_status = minishell_run(&minishell);
minishell_init(&minishell, envp);
minishell_run(&minishell);
minishell_clear(&minishell);
return (exit_status);
return (minishell.exit_status);
}

View File

@@ -6,13 +6,16 @@
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/10/20 20:51:33 by sede-san #+# #+# */
/* Updated: 2025/12/01 19:02:18 by sede-san ### ########.fr */
/* Updated: 2026/02/09 18:48:34 by sede-san ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
#include "core.h"
#include "parser.h"
#include "executor.h"
int minishell_init(
void minishell_init(
t_minishell *minishell,
char **envp
){
@@ -20,32 +23,34 @@ int minishell_init(
set_envp(envp, minishell);
set_builtins(minishell);
if (minishell->variables.environment == NULL || minishell->builtins == NULL)
{
minishell_clear(minishell);
return (0);
}
return (1);
}
u_int8_t minishell_run(
void minishell_run(
t_minishell *minishell
){
char *line;
t_command command;
char *line;
t_list *commands;
line = NULL;
while (minishell->exit == 0)
if (minishell == NULL)
{
line = readline("minishell > ");
if (*line)
{
add_history(line);
command = parse(line, minishell);
execute(command, minishell);
}
ft_free((void **)&line);
minishell->exit_status = EXIT_FAILURE;
return ;
}
while (!minishell->exit)
{
line = readline(DEFAULT_PS1);
if (line != NULL)
{
if (*line != '\0')
{
add_history(line);
commands = parse(line, minishell);
execute(commands, minishell);
}
free(line);
}
}
return (minishell->exit_status);
}
void minishell_clear(
@@ -56,5 +61,4 @@ void minishell_clear(
ft_hashmap_clear(&minishell->variables.environment, free);
if (minishell->builtins != NULL)
ft_hashmap_clear_keys(&minishell->builtins);
ft_bzero(minishell, sizeof(t_minishell));
}

79
src/parser/lexer.c Normal file
View File

@@ -0,0 +1,79 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* lexer.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2026/02/09 18:56:41 by sede-san #+# #+# */
/* Updated: 2026/02/09 20:42:50 by sede-san ### ########.fr */
/* */
/* ************************************************************************** */
#include "core.h"
#include "parser.h"
static t_token *tokenize(const char *line, size_t *start);
static t_token_type get_token_type(const char *str);
t_list *lex(
const char *line
) {
t_list *tokens;
t_token *token;
size_t i;
tokens = NULL;
i = 0;
while (line[i] != '\0')
{
// ignore spaces
while (ft_isspace(line[i]))
i++;
// create token
token = tokenize(line, &i);
// add token to list
if (token != NULL)
ft_lstadd_back(&tokens, ft_lstnew(token));
}
return (tokens);
}
static t_token *tokenize(const char *line, size_t *start) {
t_token *token;
t_token_type type;
token = NULL;
if (line == NULL || line[*start] == '\0')
return (NULL);
type = get_token_type(line + *start);
(void)type;
// if (type != TOKEN_WORD)
// token = token_new(type, NULL);
// else
// token = read_word(line, start);
// if (token == NULL)
// (*start) += ft_strlen(token->value);
return (token);
}
static t_token_type get_token_type(const char *str)
{
size_t i;
static const t_map_entry tokens[TOKENS_COUNT] = {
{PIPE_STR, (void *)TOKEN_PIPE},
{REDIRECT_IN_STR, (void *)TOKEN_REDIRECT_IN},
{REDIRECT_OUT_STR, (void *)TOKEN_REDIRECT_OUT},
{APPEND_STR, (void *)TOKEN_APPEND},
{HEREDOC_STR, (void *)TOKEN_HEREDOC}
};
i = 0;
while (i < TOKENS_COUNT)
{
if (ft_strcmp(str, tokens[i].key) == 0)
return ((t_token_type)tokens[i].value);
i++;
}
return (TOKEN_WORD);
}

View File

@@ -6,73 +6,295 @@
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/10/22 18:37:38 by sede-san #+# #+# */
/* Updated: 2025/10/23 22:53:35 by sede-san ### ########.fr */
/* Updated: 2026/02/09 18:50:43 by sede-san ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
#include "parser.h"
static char **expand_envs(char **argv);
static int count_argv(char **argv);
// parse exclusive
static char *extract_next_command(char *line, size_t *index);
static char *trim_whitespaces(char *line, size_t *start, size_t *end);
// static void set_pipes(t_list *commands);
char *parse(
// common
static void find_boundary(char *line, size_t *index, char bound_char);
// command exclusive
static t_command *cmdnew(char *line, t_minishell *minishell);
static void set_argv(t_command *command, char *line, t_minishell *minishell);
static void expand_envs(char *arg, t_minishell *minishell);
static char **lst_to_argv(t_list *argv_list);
static void set_argc(t_command *command);
static void set_infile(t_command *command);
static void set_outfile(t_command *command);
static void set_path(t_command *command, t_minishell *minishell);
static u_int8_t path_is_solved(char *cmd_name, t_minishell *msh);
static char *solve_path(char *command_name, t_minishell *minishell);
t_list *parse(
char *line,
t_minishell *minishell
){
t_command command;
) {
t_list *commands;
t_list *tokens;
t_command *command;
char *command_str;
size_t i;
if (!line || !*line)
if (line == NULL)
return (NULL);
(void)minishell;
command.argv = expand_envs(ft_split(line, SPACE));
command.argc = count_argv(command.argv);
if (!command.argc)
return (NULL);
////////////////////////////////////////////////////////////////////////////////
//* DEBUG
// int i = -1;
// while (command.argv[++i])
// printf("argv[%i]: %s\n", i, command.argv[i]);
////////////////////////////////////////////////////////////////////////////////
commands = NULL;
i = 0;
while (line[i] != '\0')
{
tokens = tokenize();
command_str = extract_next_command(line, &i);
if (command_str != NULL)
{
command = cmdnew(command_str, minishell);
free(command_str);
if (command != NULL)
ft_lstadd_back(&commands, ft_lstnew(command));
}
}
// set_pipes(commands);
return (commands);
}
// static void set_pipes(
// t_list *commands
// ) {
// t_list *current_command;
// t_list *previous_command;
// t_list *next_command;
// t_command *command;
// previous_command = NULL;
// current_command = commands;
// while (current_command != NULL)
// {
// command = (t_command *)current_command->content;
// if (previous_command != NULL)
// command->piped_from = (t_command *)previous_command->content;
// next_command = current_command->next;
// if (next_command != NULL)
// command->piped_to = (t_command *)next_command->content;
// previous_command = current_command;
// current_command = current_command->next;
// }
// }
static char *extract_next_command(
char *line,
size_t *index
) {
char *command_str;
size_t start;
size_t end;
start = *index;
find_boundary(line, index, '|');
end = *index;
command_str = trim_whitespaces(line, &start, &end);
while (line[*index] == '|' || ft_isspace(line[*index]))
(*index)++;
return (command_str);
}
static void find_boundary(
char *line,
size_t *index,
char bound_char
) {
bool in_single_quote;
bool in_double_quote;
in_single_quote = false;
in_double_quote = false;
while (line[*index] != '\0')
{
if (line[*index] == '\'' && !in_double_quote)
in_single_quote = !in_single_quote;
else if (line[*index] == '"' && !in_single_quote)
in_double_quote = !in_double_quote;
if (line[*index] == bound_char && !in_single_quote && !in_double_quote)
break ;
(*index)++;
}
}
static char *trim_whitespaces(
char *line,
size_t *start,
size_t *end
) {
while (*start < *end && ft_isspace(line[*start]))
(*start)++;
while (*end > *start && ft_isspace(line[*end - 1]))
(*end)--;
if (*end > *start)
return (ft_substr(line, *start, *end - *start));
return (NULL);
}
static char **expand_envs(
char **argv
){
int i;
char *env;
static t_command *cmdnew(
char *line,
t_minishell *minishell
) {
t_command *command;
if (!argv)
command = (t_command *)ft_calloc(1, sizeof(t_command));
if (!command)
return (NULL);
else if (!*argv) // check if ft_split returned and empty matrix
// resolve_heredoc
set_argv(command, line, minishell);
if (!command->argv)
{
ft_free_split(argv);
free(command);
return (NULL);
}
i = -1;
while (argv[++i])
set_argc(command);
set_infile(command);
set_outfile(command);
set_path(command, minishell);
return (command);
}
static void set_argv(
t_command *command,
char *line,
t_minishell *minishell
) {
t_list *argv_list;
char *arg;
size_t i;
size_t start;
size_t end;
if (line == NULL)
return ;
i = 0;
argv_list = NULL;
while (line[i] != '\0')
{
if (!ft_strchr(argv[i], DOLLAR)
|| (ft_strchr(argv[i], DOLLAR) && ft_strchr(argv[i], SINGLE_QUOTE) && ft_strchr(argv[i] + (ft_strchr(argv[i], SINGLE_QUOTE) + 1 - argv[i]), SINGLE_QUOTE))) // env is surrounded by single quote
continue ;
env = getenv(ft_strchr(argv[i], DOLLAR) + 1);
free(argv[i]);
if (env)
argv[i] = ft_strdup(env);
else
argv[i] = ft_strdup("");
start = i;
find_boundary(line, &i, ' ');
end = i;
arg = trim_whitespaces(line, &start, &end);
expand_envs(arg, minishell);
if (arg != NULL)
ft_lstadd_back(&argv_list, ft_lstnew(arg));
while (ft_isspace(line[i]))
i++;
}
command->argv = lst_to_argv(argv_list);
ft_lstclear(&argv_list, free);
}
static void expand_envs(
char *arg,
t_minishell *minishell
) {
// TODO
(void)arg;
(void)minishell;
}
static char **lst_to_argv(
t_list *argv_list
) {
char **argv;
t_list *current_arg;
size_t i;
argv = (char **)ft_calloc(ft_lstsize(argv_list) + 1, sizeof(char *));
if (!argv)
return (NULL);
i = 0;
current_arg = argv_list;
while (current_arg != NULL)
{
argv[i] = ft_strdup((char *)current_arg->content);
i++;
current_arg = current_arg->next;
}
return (argv);
}
static int count_argv(
char **argv
){
int i;
static void set_argc(
t_command *command
) {
int argc;
i = 0;
while (argv[i])
i++;
return (i);
argc = 0;
while (command->argv[argc] != NULL)
argc++;
command->argc = argc;
}
static void set_infile(
t_command *command
) {
// test_infile
command->infile = -1;
}
static void set_outfile(
t_command *command
) {
// test_outfile
command->outfile = STDOUT_FILENO;
}
static void set_path(
t_command *command,
t_minishell *minishell
) {
char *command_path;
char *command_name;
command_name = command->argv[0];
if (!path_is_solved(command_name, minishell))
command_path = solve_path(command_name, minishell);
else
command_path = ft_strdup(command_name);
command->path = command_path;
}
static char *solve_path(
char *command_name,
t_minishell *minishell
){
char *command_path;
char **path_env;
size_t i;
path_env = ft_split(get_env("PATH", minishell), ':');
if (!path_env)
return (NULL);
command_path = NULL;
i = -1;
while (!command_path && path_env[++i])
{
command_path = ft_strnjoin(3, path_env[i], "/", command_name);
if (command_path != NULL && access(command_path, F_OK) != EXIT_SUCCESS)
{
free(command_path);
command_path = NULL;
}
}
ft_free_split(path_env);
return (command_path);
}
static u_int8_t path_is_solved(
char *command_name,
t_minishell *minishell
){
return (ft_strncmp(command_name, "/", 1) == 0
|| (command_name[1] && ft_strncmp(command_name, "./", 2) == 0)
|| (command_name[2] && ft_strncmp(command_name, "../", 3) == 0)
|| is_builtin(command_name, minishell)
);
}

View File

@@ -6,11 +6,12 @@
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/12/01 09:12:39 by sede-san #+# #+# */
/* Updated: 2025/12/01 17:27:57 by sede-san ### ########.fr */
/* Updated: 2026/02/08 19:44:15 by sede-san ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
#include "core.h"
/**
* @brief Parses and stores environment variables from envp array into a hashmap
@@ -117,8 +118,7 @@ char **get_envp(
size_t i;
env_list = ft_hashmap_entries(msh->variables.environment);
envp = (char **)malloc(
(msh->variables.environment->size + 1) * sizeof(char *));
envp = (char **)malloc((msh->variables.environment->size + 1) * sizeof(char *));
if (envp != NULL)
{
i = 0;