Merge branch 'feature/executor-gl' into solo
This commit is contained in:
@@ -12,23 +12,53 @@
|
||||
|
||||
#include "builtins.h"
|
||||
|
||||
u_int8_t set_builtins(
|
||||
t_minishell *minishell
|
||||
) {
|
||||
minishell->builtins
|
||||
= ft_hashmap_new(4, ft_hashmap_hashstr, ft_hashmap_strcmp);
|
||||
if (minishell->builtins == NULL)
|
||||
static uint8_t register_builtin(
|
||||
t_minishell *minishell,
|
||||
const char *name,
|
||||
t_builtin_func builtin
|
||||
)
|
||||
{
|
||||
char *key;
|
||||
|
||||
key = ft_strdup(name);
|
||||
if (key == NULL)
|
||||
return (0);
|
||||
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);
|
||||
ft_hashmap_put(minishell->builtins, key, builtin);
|
||||
if (!ft_hashmap_contains_key(minishell->builtins, name))
|
||||
{
|
||||
free(key);
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
u_int8_t is_builtin(
|
||||
uint8_t set_builtins(
|
||||
t_minishell *minishell
|
||||
) {
|
||||
minishell->builtins
|
||||
= ft_hashmap_new(7, ft_hashmap_hashstr, ft_hashmap_strcmp);
|
||||
if (minishell->builtins == NULL)
|
||||
return (0);
|
||||
if (!register_builtin(minishell, "cd", builtin_cd)
|
||||
|| !register_builtin(minishell, "echo", builtin_echo)
|
||||
|| !register_builtin(minishell, "env", builtin_env)
|
||||
|| !register_builtin(minishell, "exit", builtin_exit)
|
||||
|| !register_builtin(minishell, "export", builtin_export)
|
||||
|| !register_builtin(minishell, "pwd", builtin_pwd)
|
||||
|| !register_builtin(minishell, "unset", builtin_unset))
|
||||
{
|
||||
ft_hashmap_clear_keys(&minishell->builtins);
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
uint8_t is_builtin(
|
||||
const char *command_name,
|
||||
t_minishell *minishell
|
||||
) {
|
||||
if (command_name == NULL || minishell == NULL
|
||||
|| minishell->builtins == NULL)
|
||||
return (0);
|
||||
return (ft_hashmap_contains_key(minishell->builtins, command_name));
|
||||
}
|
||||
|
||||
@@ -12,43 +12,104 @@
|
||||
|
||||
#include "builtins.h"
|
||||
|
||||
static u_int8_t handle_error(t_command cmd, t_minishell *msh, char *path);
|
||||
static uint8_t handle_error(void);
|
||||
static void update_pwd_vars(t_minishell *msh, char *oldpwd);
|
||||
static char *get_path_from_env(
|
||||
t_minishell *msh,
|
||||
const char *env_name,
|
||||
const char *error,
|
||||
uint8_t *status
|
||||
);
|
||||
static char *resolve_cd_path(
|
||||
t_command cmd,
|
||||
t_minishell *msh,
|
||||
uint8_t *status
|
||||
);
|
||||
|
||||
u_int8_t builtin_cd(
|
||||
uint8_t builtin_cd(
|
||||
t_command cmd,
|
||||
t_minishell *msh
|
||||
){
|
||||
char *path;
|
||||
char *oldpwd;
|
||||
uint8_t status;
|
||||
bool show_pwd;
|
||||
|
||||
if (cmd.argc > 2)
|
||||
{
|
||||
ft_eputendl("minishell: cd: too many arguments");
|
||||
return (2);
|
||||
}
|
||||
else if (cmd.argc == 1)
|
||||
path = get_env("HOME", msh);
|
||||
else
|
||||
path = cmd.argv[1];
|
||||
path = resolve_cd_path(cmd, msh, &status);
|
||||
if (status != EXIT_SUCCESS)
|
||||
return (status);
|
||||
show_pwd = (cmd.argc == 2 && ft_strcmp(cmd.argv[1], "-") == 0);
|
||||
oldpwd = getcwd(NULL, 0);
|
||||
if (chdir(path) == -1)
|
||||
return (handle_error(cmd, msh, path));
|
||||
{
|
||||
free(oldpwd);
|
||||
return (handle_error());
|
||||
}
|
||||
update_pwd_vars(msh, oldpwd);
|
||||
if (show_pwd && get_env("PWD", msh) != NULL)
|
||||
ft_putendl(get_env("PWD", msh));
|
||||
free(oldpwd);
|
||||
return (EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
static u_int8_t handle_error(
|
||||
static uint8_t handle_error(void)
|
||||
{
|
||||
perror("minishell: cd");
|
||||
return (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void update_pwd_vars(
|
||||
t_minishell *msh,
|
||||
char *oldpwd
|
||||
){
|
||||
char *newpwd;
|
||||
|
||||
if (oldpwd != NULL)
|
||||
set_env("OLDPWD", oldpwd, msh);
|
||||
newpwd = getcwd(NULL, 0);
|
||||
if (newpwd != NULL)
|
||||
{
|
||||
set_env("PWD", newpwd, msh);
|
||||
free(newpwd);
|
||||
}
|
||||
}
|
||||
|
||||
static char *resolve_cd_path(
|
||||
t_command cmd,
|
||||
t_minishell *msh,
|
||||
char *path
|
||||
uint8_t *status
|
||||
){
|
||||
u_int8_t exit_code;
|
||||
|
||||
(void)msh;
|
||||
exit_code = 0;
|
||||
if (access(path, F_OK) != -1)
|
||||
// No such file or directory
|
||||
exit_code = 1;
|
||||
else if (access(path, X_OK) == -1)
|
||||
// Permission denied
|
||||
exit_code = 2;
|
||||
perror(cmd.argv[0]);
|
||||
return (exit_code);
|
||||
if (cmd.argc > 2)
|
||||
{
|
||||
ft_eputendl("minishell: cd: too many arguments");
|
||||
*status = EXIT_FAILURE;
|
||||
return (NULL);
|
||||
}
|
||||
if (cmd.argc == 2 && ft_strcmp(cmd.argv[1], "-") == 0)
|
||||
return (get_path_from_env(msh, "OLDPWD",
|
||||
"minishell: cd: OLDPWD not set", status));
|
||||
if (cmd.argc == 1)
|
||||
return (get_path_from_env(msh, "HOME",
|
||||
"minishell: cd: HOME not set", status));
|
||||
*status = EXIT_SUCCESS;
|
||||
return (cmd.argv[1]);
|
||||
}
|
||||
|
||||
static char *get_path_from_env(
|
||||
t_minishell *msh,
|
||||
const char *env_name,
|
||||
const char *error,
|
||||
uint8_t *status
|
||||
){
|
||||
char *path;
|
||||
|
||||
path = get_env(env_name, msh);
|
||||
if (path == NULL)
|
||||
{
|
||||
ft_eputendl((char *)error);
|
||||
*status = EXIT_FAILURE;
|
||||
return (NULL);
|
||||
}
|
||||
*status = EXIT_SUCCESS;
|
||||
return (path);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include "builtins.h"
|
||||
#include "echo_def.h"
|
||||
|
||||
u_int8_t builtin_echo(
|
||||
uint8_t builtin_echo(
|
||||
t_command cmd,
|
||||
t_minishell *msh
|
||||
){
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include "echo_def.h"
|
||||
|
||||
static void assign_flags(t_args *args, t_command cmd, size_t *i);
|
||||
static u_int8_t is_valid_flag(t_args *args, char *flag);
|
||||
static uint8_t is_valid_flag(t_args *args, char *flag);
|
||||
|
||||
static void assign_default_flags(
|
||||
t_args *args
|
||||
@@ -51,7 +51,7 @@ static void assign_flags(
|
||||
}
|
||||
}
|
||||
|
||||
static u_int8_t is_valid_flag(
|
||||
static uint8_t is_valid_flag(
|
||||
t_args *args,
|
||||
char *flag
|
||||
){
|
||||
|
||||
58
src/builtins/env/env.c
vendored
Normal file
58
src/builtins/env/env.c
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* env.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2026/02/09 22:05:00 by codex #+# #+# */
|
||||
/* Updated: 2026/02/09 22:05:00 by codex ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "builtins.h"
|
||||
|
||||
static void print_entry(t_map_entry *entry);
|
||||
static void print_env(t_minishell *msh);
|
||||
|
||||
uint8_t builtin_env(
|
||||
t_command cmd,
|
||||
t_minishell *msh
|
||||
)
|
||||
{
|
||||
if (cmd.argc > 1)
|
||||
{
|
||||
ft_eputendl("minishell: env: too many arguments");
|
||||
return (EXIT_FAILURE);
|
||||
}
|
||||
print_env(msh);
|
||||
return (EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
static void print_entry(
|
||||
t_map_entry *entry
|
||||
)
|
||||
{
|
||||
ft_putstr((char *)entry->key);
|
||||
ft_putchar('=');
|
||||
if (entry->value != NULL)
|
||||
ft_putstr((char *)entry->value);
|
||||
ft_putchar('\n');
|
||||
}
|
||||
|
||||
static void print_env(
|
||||
t_minishell *msh
|
||||
)
|
||||
{
|
||||
t_list *entries;
|
||||
t_list *current;
|
||||
|
||||
entries = ft_hashmap_entries(msh->variables.environment);
|
||||
current = entries;
|
||||
while (current != NULL)
|
||||
{
|
||||
print_entry((t_map_entry *)current->content);
|
||||
current = current->next;
|
||||
}
|
||||
ft_lstclear_nodes(&entries);
|
||||
}
|
||||
@@ -11,7 +11,19 @@
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "builtins.h"
|
||||
#include <stdint.h>
|
||||
#include <limits.h>
|
||||
|
||||
static uint8_t get_uint8_from_num(const char *arg, uint8_t *status);
|
||||
static uint8_t has_overflow(
|
||||
uint64_t n,
|
||||
char digit,
|
||||
uint64_t limit
|
||||
);
|
||||
static uint8_t resolve_exit_status(
|
||||
t_command cmd,
|
||||
t_minishell *msh,
|
||||
uint8_t *exit_status
|
||||
);
|
||||
|
||||
uint8_t builtin_exit(
|
||||
t_command cmd,
|
||||
@@ -19,28 +31,78 @@ uint8_t builtin_exit(
|
||||
)
|
||||
{
|
||||
uint8_t exit_status;
|
||||
|
||||
ft_eputendl("exit");
|
||||
if (cmd.argc == 1)
|
||||
exit_status = msh->exit_status;
|
||||
else if (!ft_strisnum(cmd.argv[1]))
|
||||
{
|
||||
ft_eprintf(
|
||||
"minishell: exit: %s: numeric argument required\n",
|
||||
cmd.argv[1]);
|
||||
return (2);
|
||||
}
|
||||
else if (cmd.argc > 2)
|
||||
{
|
||||
ft_eputendl("exit: too many arguments");
|
||||
return (2);
|
||||
}
|
||||
else
|
||||
exit_status = (uint8_t)ft_atol(cmd.argv[1]);
|
||||
|
||||
printf("builtin_exit: exit_status=%d\n", exit_status); // Debug print
|
||||
|
||||
msh->exit = 1;
|
||||
if (isatty(STDIN_FILENO))
|
||||
ft_eputendl("exit");
|
||||
if (!resolve_exit_status(cmd, msh, &exit_status))
|
||||
return (msh->exit_status);
|
||||
msh->exit = true;
|
||||
msh->exit_status = exit_status;
|
||||
return (exit_status);
|
||||
}
|
||||
|
||||
static uint8_t resolve_exit_status(
|
||||
t_command cmd,
|
||||
t_minishell *msh,
|
||||
uint8_t *exit_status
|
||||
){
|
||||
if (cmd.argc == 1)
|
||||
*exit_status = msh->exit_status;
|
||||
else if (!get_uint8_from_num(cmd.argv[1], exit_status))
|
||||
{
|
||||
ft_eprintf("minishell: exit: %s: numeric argument required\n",
|
||||
cmd.argv[1]);
|
||||
msh->exit = true;
|
||||
msh->exit_status = 2;
|
||||
return (0);
|
||||
}
|
||||
else if (cmd.argc > 2)
|
||||
{
|
||||
ft_eputendl("minishell: exit: too many arguments");
|
||||
msh->exit_status = EXIT_FAILURE;
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
static uint8_t get_uint8_from_num(
|
||||
const char *arg,
|
||||
uint8_t *status
|
||||
){
|
||||
uint64_t n;
|
||||
uint64_t limit;
|
||||
int sign;
|
||||
|
||||
if (arg == NULL || *arg == '\0')
|
||||
return (0);
|
||||
n = 0;
|
||||
sign = 1;
|
||||
if (*arg == '+' || *arg == '-')
|
||||
if (*arg++ == '-')
|
||||
sign = -1;
|
||||
if (*arg == '\0')
|
||||
return (0);
|
||||
limit = LONG_MAX;
|
||||
if (sign == -1)
|
||||
limit = (uint64_t)LONG_MAX + 1;
|
||||
while (*arg != '\0')
|
||||
{
|
||||
if (!ft_isdigit(*arg) || has_overflow(n, *arg, limit))
|
||||
return (0);
|
||||
n = (n * 10) + (*arg++ - '0');
|
||||
}
|
||||
*status = (uint8_t)(n * sign);
|
||||
return (1);
|
||||
}
|
||||
|
||||
static uint8_t has_overflow(
|
||||
uint64_t n,
|
||||
char digit,
|
||||
uint64_t limit
|
||||
){
|
||||
if (n > (limit / 10))
|
||||
return (1);
|
||||
if (n == (limit / 10) && (uint64_t)(digit - '0') > (limit % 10))
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
79
src/builtins/export/export.c
Normal file
79
src/builtins/export/export.c
Normal file
@@ -0,0 +1,79 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* export.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2026/02/09 22:05:00 by codex #+# #+# */
|
||||
/* Updated: 2026/02/09 22:05:00 by codex ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "builtins.h"
|
||||
|
||||
static uint8_t is_valid_identifier(const char *arg, size_t name_len);
|
||||
static uint8_t export_one(char *arg, t_minishell *msh);
|
||||
|
||||
uint8_t builtin_export(
|
||||
t_command cmd,
|
||||
t_minishell *msh
|
||||
)
|
||||
{
|
||||
uint8_t status;
|
||||
size_t i;
|
||||
|
||||
if (cmd.argc == 1)
|
||||
return (builtin_env(cmd, msh));
|
||||
status = EXIT_SUCCESS;
|
||||
i = 0;
|
||||
while (cmd.argv[++i] != NULL)
|
||||
if (export_one(cmd.argv[i], msh) != EXIT_SUCCESS)
|
||||
status = EXIT_FAILURE;
|
||||
return (status);
|
||||
}
|
||||
|
||||
static uint8_t is_valid_identifier(
|
||||
const char *arg,
|
||||
size_t name_len
|
||||
)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (name_len == 0 || arg == NULL)
|
||||
return (0);
|
||||
if (!ft_isalpha(arg[0]) && arg[0] != '_')
|
||||
return (0);
|
||||
i = 0;
|
||||
while (++i < name_len)
|
||||
if (!ft_isalnum(arg[i]) && arg[i] != '_')
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
|
||||
static uint8_t export_one(
|
||||
char *arg,
|
||||
t_minishell *msh
|
||||
)
|
||||
{
|
||||
char *eq_pos;
|
||||
char *name;
|
||||
size_t name_len;
|
||||
|
||||
eq_pos = ft_strchr(arg, '=');
|
||||
name_len = ft_strlen(arg);
|
||||
if (eq_pos != NULL)
|
||||
name_len = (size_t)(eq_pos - arg);
|
||||
if (!is_valid_identifier(arg, name_len))
|
||||
return (ft_eprintf("minishell: export: `%s': not a valid identifier\n",
|
||||
arg), EXIT_FAILURE);
|
||||
name = ft_substr(arg, 0, name_len);
|
||||
if (name == NULL)
|
||||
return (EXIT_FAILURE);
|
||||
if (eq_pos != NULL)
|
||||
set_env(name, eq_pos + 1, msh);
|
||||
else
|
||||
set_env(name, "", msh);
|
||||
free(name);
|
||||
return (EXIT_SUCCESS);
|
||||
}
|
||||
@@ -12,15 +12,21 @@
|
||||
|
||||
#include "builtins.h"
|
||||
|
||||
u_int8_t builtin_pwd(
|
||||
uint8_t builtin_pwd(
|
||||
t_command cmd,
|
||||
t_minishell *msh
|
||||
){
|
||||
char cwd[PATH_MAX];
|
||||
char *cwd;
|
||||
|
||||
(void)cmd;
|
||||
(void)msh;
|
||||
if (getcwd(cwd, PATH_MAX) != NULL)
|
||||
ft_putendl(cwd);
|
||||
cwd = getcwd(NULL, 0);
|
||||
if (cwd == NULL)
|
||||
{
|
||||
perror("minishell: pwd");
|
||||
return (EXIT_FAILURE);
|
||||
}
|
||||
ft_putendl(cwd);
|
||||
free(cwd);
|
||||
return (EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
61
src/builtins/unset/unset.c
Normal file
61
src/builtins/unset/unset.c
Normal file
@@ -0,0 +1,61 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* unset.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2026/02/09 22:05:00 by codex #+# #+# */
|
||||
/* Updated: 2026/02/09 22:05:00 by codex ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "builtins.h"
|
||||
|
||||
static uint8_t is_valid_identifier(const char *arg);
|
||||
static uint8_t unset_one(char *arg, t_minishell *msh);
|
||||
|
||||
uint8_t builtin_unset(
|
||||
t_command cmd,
|
||||
t_minishell *msh
|
||||
)
|
||||
{
|
||||
uint8_t status;
|
||||
size_t i;
|
||||
|
||||
status = EXIT_SUCCESS;
|
||||
i = 0;
|
||||
while (cmd.argv[++i] != NULL)
|
||||
if (unset_one(cmd.argv[i], msh) != EXIT_SUCCESS)
|
||||
status = EXIT_FAILURE;
|
||||
return (status);
|
||||
}
|
||||
|
||||
static uint8_t is_valid_identifier(
|
||||
const char *arg
|
||||
)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (arg == NULL || *arg == '\0')
|
||||
return (0);
|
||||
if (!ft_isalpha(arg[0]) && arg[0] != '_')
|
||||
return (0);
|
||||
i = 0;
|
||||
while (arg[++i] != '\0')
|
||||
if (!ft_isalnum(arg[i]) && arg[i] != '_')
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
|
||||
static uint8_t unset_one(
|
||||
char *arg,
|
||||
t_minishell *msh
|
||||
)
|
||||
{
|
||||
if (!is_valid_identifier(arg))
|
||||
return (ft_eprintf("minishell: unset: `%s': not a valid identifier\n",
|
||||
arg), EXIT_FAILURE);
|
||||
unset_env(arg, msh);
|
||||
return (EXIT_SUCCESS);
|
||||
}
|
||||
86
src/executor/command_exec.c
Normal file
86
src/executor/command_exec.c
Normal file
@@ -0,0 +1,86 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* command_exec.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2026/02/11 00:00:00 by sede-san #+# #+# */
|
||||
/* Updated: 2026/02/11 00:00:00 by sede-san ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "executor.h"
|
||||
#include "builtins.h"
|
||||
#include <errno.h>
|
||||
|
||||
static uint8_t resolve_execve_status(void)
|
||||
{
|
||||
if (errno == ENOENT)
|
||||
return (127);
|
||||
if (errno == EACCES || errno == ENOEXEC || errno == EISDIR)
|
||||
return (126);
|
||||
return (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static uint8_t execute_builtin(
|
||||
const t_command *command,
|
||||
t_minishell *minishell
|
||||
)
|
||||
{
|
||||
const t_builtin_func builtin
|
||||
= ft_hashmap_get(minishell->builtins, command->argv[0]);
|
||||
|
||||
return (builtin(*command, minishell));
|
||||
}
|
||||
|
||||
static void handle_execve_error(
|
||||
const t_command *command,
|
||||
char **envp
|
||||
)
|
||||
{
|
||||
uint8_t exit_status;
|
||||
|
||||
exit_status = resolve_execve_status();
|
||||
free_envp(envp);
|
||||
perror(command->path);
|
||||
exit(exit_status);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
uint8_t executor_execute_command(
|
||||
t_command *command,
|
||||
t_minishell *minishell
|
||||
)
|
||||
{
|
||||
if (command == NULL || command->argv == NULL || command->argv[0] == NULL)
|
||||
return (EXIT_SUCCESS);
|
||||
if (executor_is_builtin_command(command, minishell))
|
||||
return (execute_builtin(command, minishell));
|
||||
if (command->path != NULL)
|
||||
free(command->path);
|
||||
command->path = executor_resolve_command_path(command, minishell);
|
||||
if (command->path == NULL)
|
||||
{
|
||||
ft_eprintf("minishell: %s: command not found\n", command->argv[0]);
|
||||
return (127);
|
||||
}
|
||||
execute_external_command(command, minishell);
|
||||
return (EXIT_FAILURE);
|
||||
}
|
||||
@@ -6,198 +6,72 @@
|
||||
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2026/02/08 19:10:47 by sede-san #+# #+# */
|
||||
/* Updated: 2026/02/08 21:32:03 by sede-san ### ########.fr */
|
||||
/* Updated: 2026/02/11 00:00:00 by sede-san ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "executor.h"
|
||||
#include "builtins.h"
|
||||
|
||||
static inline uint8_t execute_builtin(
|
||||
const t_command *command,
|
||||
static void init_exec_state(
|
||||
t_exec_state *state,
|
||||
t_list *command_list
|
||||
)
|
||||
{
|
||||
state->exit_status = EXIT_SUCCESS;
|
||||
state->pipeline.prev_read_fd = -1;
|
||||
state->current_command = command_list;
|
||||
state->last_child_pid = -1;
|
||||
}
|
||||
|
||||
static bool fork_current_command(
|
||||
t_exec_state *state,
|
||||
t_minishell *minishell
|
||||
)
|
||||
{
|
||||
const t_builtin_func builtin
|
||||
= ft_hashmap_get(minishell->builtins, command->path);
|
||||
pid_t pid;
|
||||
|
||||
return (builtin(*command, minishell));
|
||||
}
|
||||
|
||||
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 (argv == NULL)
|
||||
return ;
|
||||
i = 0;
|
||||
while (argv[i] != NULL)
|
||||
{
|
||||
free(argv[i]);
|
||||
i++;
|
||||
}
|
||||
free(argv);
|
||||
}
|
||||
|
||||
static void cmdfree(
|
||||
t_command *command
|
||||
)
|
||||
{
|
||||
if (command == NULL)
|
||||
return ;
|
||||
cmdfree_argv(command->argv);
|
||||
free(command->path);
|
||||
free(command);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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();
|
||||
pid = fork();
|
||||
if (pid == FORK_ERROR)
|
||||
perror("fork");
|
||||
return (pid);
|
||||
return (perror("fork"), state->exit_status = EXIT_FAILURE, false);
|
||||
if (pid == 0)
|
||||
executor_child_process(state->current_command, &state->pipeline,
|
||||
minishell);
|
||||
state->last_child_pid = pid;
|
||||
return (true);
|
||||
}
|
||||
|
||||
static void setup_child_input(
|
||||
t_pipeline *pipeline
|
||||
)
|
||||
{
|
||||
if (pipeline->prev_read_fd != -1)
|
||||
{
|
||||
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,
|
||||
static bool run_current_command(
|
||||
t_exec_state *state,
|
||||
t_minishell *minishell
|
||||
)
|
||||
{
|
||||
uint8_t exit_status;
|
||||
const t_command *command = current_command->content;
|
||||
bool should_fork;
|
||||
t_command *command;
|
||||
int saved_stdin;
|
||||
int saved_stdout;
|
||||
|
||||
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)
|
||||
if (executor_create_pipe_if_needed(state->current_command,
|
||||
&state->pipeline) == PIPE_ERROR)
|
||||
return (state->exit_status = EXIT_FAILURE, false);
|
||||
should_fork = executor_is_fork_required(state->current_command,
|
||||
&state->pipeline, minishell);
|
||||
if (should_fork)
|
||||
{
|
||||
close(pipeline->pipefd[WRITE_PIPE]);
|
||||
pipeline->prev_read_fd = pipeline->pipefd[READ_PIPE];
|
||||
if (!fork_current_command(state, minishell))
|
||||
return (false);
|
||||
}
|
||||
else
|
||||
pipeline->prev_read_fd = -1;
|
||||
}
|
||||
|
||||
static uint8_t wait_for_children(void)
|
||||
{
|
||||
uint8_t exit_status;
|
||||
int status;
|
||||
|
||||
exit_status = EXIT_SUCCESS;
|
||||
while (wait(&status) > 0)
|
||||
{
|
||||
if (WIFEXITED(status))
|
||||
exit_status = WEXITSTATUS(status);
|
||||
command = state->current_command->content;
|
||||
if (!executor_apply_redirections(command, &saved_stdin, &saved_stdout))
|
||||
state->exit_status = EXIT_FAILURE;
|
||||
else
|
||||
state->exit_status = executor_execute_command(command, minishell);
|
||||
executor_restore_redirections(saved_stdin, saved_stdout);
|
||||
}
|
||||
return (exit_status);
|
||||
executor_parent_cleanup(state->current_command, &state->pipeline);
|
||||
state->current_command = state->current_command->next;
|
||||
return (true);
|
||||
}
|
||||
|
||||
uint8_t execute(
|
||||
@@ -205,26 +79,17 @@ uint8_t execute(
|
||||
t_minishell *minishell
|
||||
)
|
||||
{
|
||||
uint8_t exit_status;
|
||||
t_pipeline pipeline;
|
||||
t_list *current_command;
|
||||
pid_t pid;
|
||||
t_exec_state state;
|
||||
|
||||
pipeline.prev_read_fd = -1;
|
||||
current_command = command_list;
|
||||
while (current_command)
|
||||
init_exec_state(&state, command_list);
|
||||
while (state.current_command)
|
||||
{
|
||||
if (create_pipe_if_needed(current_command, &pipeline) == PIPE_ERROR)
|
||||
if (!run_current_command(&state, minishell))
|
||||
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);
|
||||
if (state.last_child_pid > 0)
|
||||
state.exit_status = executor_wait_for_children(state.last_child_pid);
|
||||
minishell->exit_status = state.exit_status;
|
||||
ft_lstclear(&command_list, (void (*)(void *))executor_cmdfree);
|
||||
return (state.exit_status);
|
||||
}
|
||||
|
||||
77
src/executor/path_resolver.c
Normal file
77
src/executor/path_resolver.c
Normal file
@@ -0,0 +1,77 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* path_resolver.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2026/02/11 00:00:00 by sede-san #+# #+# */
|
||||
/* Updated: 2026/02/11 00:00:00 by sede-san ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "executor.h"
|
||||
|
||||
static bool is_path_explicit(
|
||||
const char *command_name
|
||||
)
|
||||
{
|
||||
return (command_name != NULL && ft_strchr(command_name, '/') != NULL);
|
||||
}
|
||||
|
||||
static char *resolve_path_from_env(
|
||||
const char *command_name,
|
||||
t_minishell *minishell
|
||||
)
|
||||
{
|
||||
char *command_path;
|
||||
char **path_env;
|
||||
char *path_value;
|
||||
size_t i;
|
||||
|
||||
path_value = get_env("PATH", minishell);
|
||||
if (path_value == NULL)
|
||||
return (NULL);
|
||||
path_env = ft_split(path_value, ':');
|
||||
if (path_env == NULL)
|
||||
return (NULL);
|
||||
command_path = NULL;
|
||||
i = -1;
|
||||
while (!command_path && path_env[++i] != NULL)
|
||||
{
|
||||
command_path = ft_strnjoin(3, path_env[i], "/", command_name);
|
||||
if (command_path != NULL && access(command_path, X_OK) != EXIT_SUCCESS)
|
||||
{
|
||||
free(command_path);
|
||||
command_path = NULL;
|
||||
}
|
||||
}
|
||||
ft_free_split(path_env);
|
||||
return (command_path);
|
||||
}
|
||||
|
||||
static char *resolve_explicit_path(
|
||||
const char *command_name
|
||||
)
|
||||
{
|
||||
if (access(command_name, F_OK) != EXIT_SUCCESS)
|
||||
return (NULL);
|
||||
if (access(command_name, X_OK) != EXIT_SUCCESS)
|
||||
return (NULL);
|
||||
return (ft_strdup(command_name));
|
||||
}
|
||||
|
||||
char *executor_resolve_command_path(
|
||||
const t_command *command,
|
||||
t_minishell *minishell
|
||||
)
|
||||
{
|
||||
const char *command_name;
|
||||
|
||||
if (command == NULL || command->argv == NULL || command->argv[0] == NULL)
|
||||
return (NULL);
|
||||
command_name = command->argv[0];
|
||||
if (is_path_explicit(command_name))
|
||||
return (resolve_explicit_path(command_name));
|
||||
return (resolve_path_from_env(command_name, minishell));
|
||||
}
|
||||
73
src/executor/pipeline_helpers.c
Normal file
73
src/executor/pipeline_helpers.c
Normal file
@@ -0,0 +1,73 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* pipeline_helpers.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2026/02/11 00:00:00 by sede-san #+# #+# */
|
||||
/* Updated: 2026/02/11 00:00:00 by sede-san ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "executor.h"
|
||||
#include "builtins.h"
|
||||
|
||||
int executor_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);
|
||||
}
|
||||
|
||||
bool executor_is_builtin_command(
|
||||
const t_command *command,
|
||||
t_minishell *minishell
|
||||
)
|
||||
{
|
||||
if (command == NULL || command->argv == NULL || command->argv[0] == NULL)
|
||||
return (false);
|
||||
return (is_builtin(command->argv[0], minishell));
|
||||
}
|
||||
|
||||
bool executor_is_fork_required(
|
||||
t_list *current_command,
|
||||
const t_pipeline *pipeline,
|
||||
t_minishell *minishell
|
||||
)
|
||||
{
|
||||
const t_command *command;
|
||||
|
||||
command = current_command->content;
|
||||
return (pipeline->prev_read_fd != -1 || current_command->next != NULL
|
||||
|| !executor_is_builtin_command(command, minishell));
|
||||
}
|
||||
|
||||
void executor_setup_child_input(
|
||||
t_pipeline *pipeline
|
||||
)
|
||||
{
|
||||
if (pipeline->prev_read_fd != -1)
|
||||
{
|
||||
dup2(pipeline->prev_read_fd, STDIN_FILENO);
|
||||
close(pipeline->prev_read_fd);
|
||||
}
|
||||
}
|
||||
|
||||
void executor_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]);
|
||||
}
|
||||
}
|
||||
112
src/executor/process_helpers.c
Normal file
112
src/executor/process_helpers.c
Normal file
@@ -0,0 +1,112 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* process_helpers.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2026/02/11 00:00:00 by sede-san #+# #+# */
|
||||
/* Updated: 2026/02/11 00:00:00 by sede-san ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "executor.h"
|
||||
|
||||
void executor_child_process(
|
||||
t_list *current_command,
|
||||
t_pipeline *pipeline,
|
||||
t_minishell *minishell
|
||||
)
|
||||
{
|
||||
uint8_t exit_status;
|
||||
t_command *command;
|
||||
|
||||
command = current_command->content;
|
||||
executor_setup_child_input(pipeline);
|
||||
executor_setup_child_output(current_command, pipeline);
|
||||
if (!executor_apply_redirections(command, NULL, NULL))
|
||||
exit(EXIT_FAILURE);
|
||||
exit_status = executor_execute_command(command, minishell);
|
||||
exit(exit_status);
|
||||
}
|
||||
|
||||
void executor_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
|
||||
pipeline->prev_read_fd = -1;
|
||||
}
|
||||
|
||||
uint8_t executor_wait_for_children(
|
||||
pid_t last_child_pid
|
||||
)
|
||||
{
|
||||
uint8_t exit_status;
|
||||
int status;
|
||||
pid_t pid;
|
||||
|
||||
exit_status = EXIT_SUCCESS;
|
||||
pid = wait(&status);
|
||||
while (last_child_pid > 0 && pid > 0)
|
||||
{
|
||||
if (pid == last_child_pid)
|
||||
{
|
||||
if (WIFEXITED(status))
|
||||
exit_status = WEXITSTATUS(status);
|
||||
else if (WIFSIGNALED(status))
|
||||
exit_status = 128 + WTERMSIG(status);
|
||||
}
|
||||
pid = wait(&status);
|
||||
}
|
||||
return (exit_status);
|
||||
}
|
||||
|
||||
static void cmdfree_argv(
|
||||
char **argv
|
||||
)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (argv == NULL)
|
||||
return ;
|
||||
i = 0;
|
||||
while (argv[i] != NULL)
|
||||
{
|
||||
free(argv[i]);
|
||||
i++;
|
||||
}
|
||||
free(argv);
|
||||
}
|
||||
|
||||
static void cmdfree_redirection(
|
||||
t_redirection *redirection
|
||||
)
|
||||
{
|
||||
if (redirection == NULL)
|
||||
return ;
|
||||
free(redirection->target);
|
||||
free(redirection);
|
||||
}
|
||||
|
||||
void executor_cmdfree(
|
||||
t_command *command
|
||||
)
|
||||
{
|
||||
if (command == NULL)
|
||||
return ;
|
||||
cmdfree_argv(command->argv);
|
||||
free(command->path);
|
||||
ft_lstclear(&command->redirections,
|
||||
(void (*)(void *))cmdfree_redirection);
|
||||
ft_lstclear(&command->heredocs, (void (*)(void *))cmdfree_redirection);
|
||||
free(command);
|
||||
}
|
||||
111
src/executor/redirections.c
Normal file
111
src/executor/redirections.c
Normal file
@@ -0,0 +1,111 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* redirections.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2026/02/12 00:00:00 by sede-san #+# #+# */
|
||||
/* Updated: 2026/02/12 00:00:00 by sede-san ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "executor.h"
|
||||
#include <errno.h>
|
||||
|
||||
static int open_redirection_target(
|
||||
const t_redirection *redirection
|
||||
)
|
||||
{
|
||||
if (redirection->type == TOKEN_REDIRECT_IN)
|
||||
return (open(redirection->target, O_RDONLY));
|
||||
if (redirection->type == TOKEN_REDIRECT_OUT)
|
||||
return (open(redirection->target, O_WRONLY | O_CREAT | O_TRUNC, 0644));
|
||||
if (redirection->type == TOKEN_APPEND)
|
||||
return (open(redirection->target, O_WRONLY | O_CREAT | O_APPEND, 0644));
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static bool backup_stream_if_needed(
|
||||
const t_redirection *redirection,
|
||||
int *saved_stdin,
|
||||
int *saved_stdout
|
||||
)
|
||||
{
|
||||
if (redirection->type == TOKEN_REDIRECT_IN && saved_stdin != NULL
|
||||
&& *saved_stdin == -1)
|
||||
{
|
||||
*saved_stdin = dup(STDIN_FILENO);
|
||||
if (*saved_stdin == -1)
|
||||
return (perror("dup"), false);
|
||||
}
|
||||
if ((redirection->type == TOKEN_REDIRECT_OUT
|
||||
|| redirection->type == TOKEN_APPEND) && saved_stdout != NULL
|
||||
&& *saved_stdout == -1)
|
||||
{
|
||||
*saved_stdout = dup(STDOUT_FILENO);
|
||||
if (*saved_stdout == -1)
|
||||
return (perror("dup"), false);
|
||||
}
|
||||
return (true);
|
||||
}
|
||||
|
||||
bool executor_apply_redirections(
|
||||
const t_command *command,
|
||||
int *saved_stdin,
|
||||
int *saved_stdout
|
||||
)
|
||||
{
|
||||
t_list *node;
|
||||
t_redirection *redirection;
|
||||
int fd;
|
||||
|
||||
if (saved_stdin != NULL)
|
||||
*saved_stdin = -1;
|
||||
if (saved_stdout != NULL)
|
||||
*saved_stdout = -1;
|
||||
if (command == NULL || command->redirections == NULL)
|
||||
return (true);
|
||||
node = command->redirections;
|
||||
while (node != NULL)
|
||||
{
|
||||
redirection = (t_redirection *)node->content;
|
||||
if (redirection == NULL || redirection->target == NULL)
|
||||
return (false);
|
||||
if (!backup_stream_if_needed(redirection, saved_stdin, saved_stdout))
|
||||
return (false);
|
||||
fd = open_redirection_target(redirection);
|
||||
if (fd == -1)
|
||||
return (perror(redirection->target), false);
|
||||
if (redirection->type == TOKEN_REDIRECT_IN
|
||||
&& dup2(fd, STDIN_FILENO) == -1)
|
||||
return (close(fd), perror("dup2"), false);
|
||||
if ((redirection->type == TOKEN_REDIRECT_OUT
|
||||
|| redirection->type == TOKEN_APPEND)
|
||||
&& dup2(fd, STDOUT_FILENO) == -1)
|
||||
return (close(fd), perror("dup2"), false);
|
||||
close(fd);
|
||||
node = node->next;
|
||||
}
|
||||
return (true);
|
||||
}
|
||||
|
||||
void executor_restore_redirections(
|
||||
int saved_stdin,
|
||||
int saved_stdout
|
||||
)
|
||||
{
|
||||
if (saved_stdin != -1)
|
||||
{
|
||||
if (dup2(saved_stdin, STDIN_FILENO) == -1)
|
||||
perror("dup2");
|
||||
close(saved_stdin);
|
||||
}
|
||||
if (saved_stdout != -1)
|
||||
{
|
||||
if (dup2(saved_stdout, STDOUT_FILENO) == -1)
|
||||
perror("dup2");
|
||||
close(saved_stdout);
|
||||
}
|
||||
}
|
||||
@@ -46,7 +46,7 @@ void minishell_run(
|
||||
{
|
||||
add_history(line);
|
||||
commands = parse(line, minishell);
|
||||
execute(commands, minishell);
|
||||
minishell->exit_status = execute(commands, minishell);
|
||||
}
|
||||
free(line);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/* By: sede-san <sede-san@student.42madrid.com +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/10/22 18:37:38 by sede-san #+# #+# */
|
||||
/* Updated: 2026/02/12 20:55:49 by sede-san ### ########.fr */
|
||||
/* Updated: 2026/02/12 21:25:39 by sede-san ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
@@ -488,57 +488,3 @@ t_list *ft_lstfind(
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
// void print_command_info(
|
||||
// t_command *command
|
||||
// )
|
||||
// {
|
||||
// printf("Command:\n");
|
||||
// printf(" argc: %d\n", command->argc);
|
||||
// printf(" argv: [");
|
||||
// for (int i = 0; i < command->argc; i++)
|
||||
// {
|
||||
// printf("%s", command->argv[i]);
|
||||
// if (i < command->argc - 1)
|
||||
// printf(", ");
|
||||
// }
|
||||
// printf("]\n");
|
||||
// printf(" path: %s\n", command->path);
|
||||
// printf(" redirections:\n");
|
||||
// t_list *redirection_node = command->redirections;
|
||||
// while (redirection_node != NULL)
|
||||
// {
|
||||
// t_redirection *redirection = (t_redirection *)redirection_node->content;
|
||||
// printf(" type: %d, target: %s\n", redirection->type, redirection->target);
|
||||
// redirection_node = redirection_node->next;
|
||||
// }
|
||||
// printf(" heredocs:\n");
|
||||
// t_list *heredoc_node = command->heredocs;
|
||||
// while (heredoc_node != NULL)
|
||||
// {
|
||||
// t_redirection *heredoc = (t_redirection *)heredoc_node->content;
|
||||
// printf(" type: %d, target: %s\n", heredoc->type, heredoc->target);
|
||||
// heredoc_node = heredoc_node->next;
|
||||
// }
|
||||
// }
|
||||
|
||||
// int main(int argc, char const *argv[], char **envp)
|
||||
// {
|
||||
// t_minishell minishell;
|
||||
// t_list *commands;
|
||||
// char *line;
|
||||
|
||||
// if (argc != 2)
|
||||
// return (EXIT_FAILURE);
|
||||
|
||||
// minishell_init(&minishell, envp);
|
||||
|
||||
// line = ft_strdup(argv[1]);
|
||||
// commands = parse(line, NULL);
|
||||
// ft_lstiter(commands, (void (*)(void *))print_command_info);
|
||||
// if (line != NULL)
|
||||
// free(line);
|
||||
// if (commands != NULL)
|
||||
// ft_lstclear(&commands, (void (*)(void *))command_clear);
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
@@ -32,26 +32,37 @@ void set_envp(
|
||||
char **envp,
|
||||
t_minishell *msh
|
||||
) {
|
||||
char **splitted_env;
|
||||
char *equal_sign;
|
||||
char *key;
|
||||
char *value;
|
||||
|
||||
if (msh == NULL || envp == NULL)
|
||||
return ;
|
||||
msh->variables.environment
|
||||
= ft_hashmap_new(32, ft_hashmap_hashstr, ft_hashmap_strcmp);
|
||||
if (msh == NULL)
|
||||
{
|
||||
ft_hashmap_clear(&msh->variables.environment, free);
|
||||
if (msh->variables.environment == NULL)
|
||||
return ;
|
||||
}
|
||||
while (*envp != NULL)
|
||||
{
|
||||
splitted_env = ft_split(*envp, '=');
|
||||
if (splitted_env == 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,
|
||||
ft_strdup(splitted_env[0]), ft_strdup(splitted_env[1]));
|
||||
ft_free_split(splitted_env);
|
||||
ft_hashmap_put(msh->variables.environment, key, value);
|
||||
envp++;
|
||||
}
|
||||
}
|
||||
@@ -118,7 +129,9 @@ 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;
|
||||
|
||||
41
src/variables/environment_unset.c
Normal file
41
src/variables/environment_unset.c
Normal file
@@ -0,0 +1,41 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* 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;
|
||||
}
|
||||
Reference in New Issue
Block a user