From a17f3f9c9ad50bcb61d6a3da356e7fe0e632f0bc Mon Sep 17 00:00:00 2001 From: Lukas Jiriste Date: Sat, 31 Aug 2024 10:25:48 +0200 Subject: [PATCH] Refactor input_method.c to rl and noleaks versions --- Makefile | 14 +- inc/minishell.h | 6 +- src/execution.c.orig | 1078 ++++++++++++++++++++++ src/main.c | 61 +- src/noleaks_input.c | 74 ++ src/{input_method.c => readline_input.c} | 79 +- 6 files changed, 1198 insertions(+), 114 deletions(-) create mode 100644 src/execution.c.orig create mode 100644 src/noleaks_input.c rename src/{input_method.c => readline_input.c} (55%) diff --git a/Makefile b/Makefile index d9ab6f9..fe257ef 100644 --- a/Makefile +++ b/Makefile @@ -24,7 +24,6 @@ INCLUDE := $(addprefix -I, $(INCDIR)) SRCDIR := src SOURCES := main.c \ - input_method.c \ env.c \ vars.c \ input_handling.c \ @@ -42,6 +41,12 @@ SOURCES := main.c \ builtins/unset.c \ builtins/exit.c \ +ifneq ("$(wildcard .noleaks)","") + SOURCES += noleaks_input.c +else + SOURCES += readline_input.c +endif + SOURCES := $(addprefix $(SRCDIR)/, $(SOURCES)) OBJECTS := $(SOURCES:.c=.o) @@ -50,8 +55,6 @@ NAME := minishell all : $(NAME) -.PHONY : Libft/libft.a - debug : .debug $(MAKE) -C Libft debug $(MAKE) all @@ -62,16 +65,19 @@ nodebug : $(MAKE) shallow_re noleaks : .noleaks + $(RM) $(SRCDIR)/readline_input.o $(MAKE) all readline : - $(RM) .noleaks + $(RM) $(SRCDIR)/noleaks_input.o .noleaks $(MAKE) shallow_re .% : $(MAKE) shallow_fclean touch $@ +.PHONY : Libft/libft.a + $(NAME) : $(OBJECTS) Libft/libft.a $(CC) $(CFLAGS) -o $@ $^ $(LINKS) diff --git a/inc/minishell.h b/inc/minishell.h index e77f81b..be6479a 100644 --- a/inc/minishell.h +++ b/inc/minishell.h @@ -6,7 +6,7 @@ /* By: ljiriste +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/02 13:22:57 by ljiriste #+# #+# */ -/* Updated: 2024/08/29 16:17:10 by ljiriste ### ########.fr */ +/* Updated: 2024/08/31 10:04:30 by ljiriste ### ########.fr */ /* */ /* ************************************************************************** */ @@ -19,9 +19,11 @@ extern volatile sig_atomic_t g_last_signal; -void minishell_flush(void); +void handler(int sig_num); + char *get_line(void); void terminate_input(void); +void set_input_handler(void); void handle_input(char **line, t_execution_env *env); diff --git a/src/execution.c.orig b/src/execution.c.orig new file mode 100644 index 0000000..e762104 --- /dev/null +++ b/src/execution.c.orig @@ -0,0 +1,1078 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* execution.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: lnikolov >>>>>> 42/trunk +/* */ +/* ************************************************************************** */ + +#include "execution.h" +#include "builtins.h" +#include "minishell_structs.h" +#include "minishell.h" +#include "libft.h" +#include +#include +#include +#include + +#include +#include +#include + +int is_token_type(const t_parse_tree_node *node, const char *type) +{ + return (!ft_strcmp(node->token.type, type)); +} + +void clear_old(t_vec *assignments, const char *new) +{ + size_t i; + char **assignment; + + i = assignments->size; + while (i > 0) + { + --i; + assignment = ft_vec_access(assignments, i); + if (cmp_var_name(*assignment, new)) + continue ; + ft_vec_erase(assignments, i, free); + } + return ; +} + +int add_word(t_vec *exp_str, const char *word, const t_execution_env *env, int quote); + +int add_assignment(t_vec *assignments, const char *assignment, const t_execution_env *env) +{ + t_vec advanced_copy; + char *copy; + + if (ft_vec_init(&advanced_copy, sizeof(char)) != success) + return (1); + if (add_word(&advanced_copy, assignment, env, 0)) + return (1); + *(char *)ft_vec_access(&advanced_copy, advanced_copy.size - 1) = '\0'; + copy = advanced_copy.vec; + unquote_field(copy); + clear_old(assignments, copy); + if (ft_vec_append(assignments, ©) == success) + return (0); + free(copy); + return (1); +} + +int save_assignments_prefix(t_vec *assignments, t_parse_tree_node *prefix, const t_execution_env *env) +{ + size_t i; + t_parse_tree_node *subnode; + + i = 0; + while (i < prefix->children.size) + { + subnode = ft_vec_access(&prefix->children, i); + if (is_token_type(subnode, "ASSIGNMENT_WORD")) + { + if (add_assignment(assignments, subnode->token.str, env)) + return (1); + } + else if (is_token_type(subnode, "cmd_prefix")) + if (save_assignments_prefix(assignments, subnode, env)) + return (1); + ++i; + } + return (0); +} + +int save_assignments(t_vec *assignments, t_parse_tree_node *simple_command, const t_execution_env *env) +{ + t_parse_tree_node *subnode; + + if (ft_vec_init(assignments, sizeof(char *)) != success) + return (1); + subnode = ft_vec_access(&simple_command->children, 0); + if (is_token_type(subnode, "cmd_prefix")) + return (save_assignments_prefix(assignments, subnode, env)); + return (0); +} + +char *get_word(const t_parse_tree_node *parent) +{ + char *res; + const t_parse_tree_node *word = ft_vec_caccess(&parent->children, 0); + + res = ft_strdup(word->token.str); + return (res); +} + +int expand_filename(char **filename, const t_execution_env *env) +{ + t_vec advanced_copy; + + if (ft_vec_init(&advanced_copy, sizeof(char)) != success) + return (1); + if (add_word(&advanced_copy, *filename, env, 0)) + { + ft_vec_free(&advanced_copy, NULL); + return (1); + } + free(*filename); + *filename = advanced_copy.vec; + filename[0][advanced_copy.size - 1] = '\0'; + unquote_field(*filename); + return (0); +} + +int add_redirection_file(t_vec *redirections, t_parse_tree_node *io_file, int fd, const t_execution_env *env) +{ + t_redirection redir; + const t_parse_tree_node *operator; + char *filename; + int sec_fd; + + filename = get_word(ft_vec_caccess(&io_file->children, 1)); + if (!filename) + return (1); + expand_filename(&filename, env); + operator = ft_vec_caccess(&io_file->children, 0); + if (is_token_type(operator, "LESS")) + { + if (fd == -1) + fd = STDIN_FILENO; + sec_fd = open(filename, O_RDONLY); + if (sec_fd < 0) + { + free(filename); + return (1); + } + redir = (t_redirection){.from_to_fds[0] = fd, .from_to_fds[1] = sec_fd}; + } + else + { + if (fd < 0) + fd = STDOUT_FILENO; + if (is_token_type(operator, "GREAT")) + sec_fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH); + else + sec_fd = open(filename, O_CREAT | O_WRONLY | O_APPEND, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH); + if (sec_fd == -1) + { + free(filename); + return (1); + } + redir = (t_redirection){.from_to_fds[0] = fd, .from_to_fds[1] = sec_fd}; + } + free(filename); + return (ft_vec_append(redirections, &redir) != success); +} + +int write_line_to_pipe(int pipe_fd, const char *line, const t_execution_env *env, int expand) +{ + size_t i; + char *var; + const char *value; + + i = 0; + while (line[i]) + { + if (line[i] != '$' || !expand) + { + ft_dprintf(pipe_fd, "%c", line[i]); + ++i; + continue ; + } + ++i; + var = get_var_name(line + i); + if (!var) + return (1); + value = get_env_var_value(env, var); + if (value) + ft_dprintf(pipe_fd, "%s", value); + i += ft_strlen(var); + free(var); + } + return (0); +} + +char *unquote_delimiter(const char *str) +{ + size_t i; + char *res; + char quote_char; + + res = ft_strdup(str); + if (!res) + return (NULL); + i = 0; + quote_char = '\0'; + while (res[i]) + { + if ((res[i] == '"' || res[i] == '\'')) + { + if (!quote_char) + { + quote_char = res[i]; + ft_memmove(res + i, res + i + 1, ft_strlen(res + i + 1) + 1); + continue ; + } + else if (res[i] == quote_char) + { + quote_char = '\0'; + ft_memmove(res + i, res + i + 1, ft_strlen(res + i + 1) + 1); + continue ; + } + } + ++i; + } + return (res); +} + +int here_file_to_pipe(int pipe_fd, const char *delimiter, const t_execution_env *env) +{ + int expand; + char *line; + char *unquoted_delimiter; + + unquoted_delimiter = unquote_delimiter(delimiter); + if (!unquoted_delimiter) + return (1); + expand = !ft_strcmp(unquoted_delimiter, delimiter); + ft_printf("> "); + line = get_next_line(STDIN_FILENO); + while (line && ft_strncmp(line, unquoted_delimiter, ft_strlen(line) - 1)) + { + if (write_line_to_pipe(pipe_fd, line, env, expand)) + { + get_next_line(-1); + free(line); + free(unquoted_delimiter); + return (1); + } + free(line); + ft_printf("> "); + line = get_next_line(STDIN_FILENO); + } + if (!line) + ft_printf("minishell: warning: here-document delimited by EOF instead of %s!\n", unquoted_delimiter); + get_next_line(-1); + free(line); + free(unquoted_delimiter); + return (0); +} + +int add_redirection_here(t_vec *redirections, t_parse_tree_node *io_here, int fd, const t_execution_env *env) +{ + char *delimiter; + int pipe_fds[2]; + int err; + t_redirection redir; + + delimiter = get_word(ft_vec_caccess(&io_here->children, 1)); + if (!delimiter) + return (1); + if (fd == -1) + fd = STDIN_FILENO; + if (pipe(pipe_fds)) + { + free(delimiter); + return (1); + } + err = here_file_to_pipe(pipe_fds[1], delimiter, env); + close(pipe_fds[1]); + free(delimiter); + if (err) + return (1); + redir = (t_redirection){.from_to_fds[0] = fd, .from_to_fds[1] = pipe_fds[0]}; + return (ft_vec_append(redirections, &redir) != success); +} + +int add_redirection(t_vec *redirections, t_parse_tree_node *redirect, const t_execution_env *env) +{ + int fd; + t_parse_tree_node *subnode; + + fd = -1; + subnode = ft_vec_access(&redirect->children, 0); + if (redirect->children.size == 2) + { + fd = ft_atoi(subnode->token.str); + if (fd < 0) + fd = -2; + subnode = ft_vec_access(&redirect->children, 1); + } + if (is_token_type(subnode, "io_file")) + return (add_redirection_file(redirections, subnode, fd, env)); + else + return (add_redirection_here(redirections, subnode, fd, env)); +} + +int save_redirections_psfix(t_vec *redirections, t_parse_tree_node *node, const t_execution_env *env) +{ + size_t i; + t_parse_tree_node *subnode; + + i = 0; + while (i < node->children.size) + { + subnode = ft_vec_access(&node->children, i); + if (is_token_type(subnode, "io_redirect")) + { + if (add_redirection(redirections, subnode, env)) + return (1); + } + else if (is_token_type(subnode, "cmd_suffix") || is_token_type(subnode, "cmd_prefix")) + if (save_redirections_psfix(redirections, subnode, env)) + return (1); + ++i; + } + return (0); +} + +int save_redirections(t_vec *redirections, t_parse_tree_node *simple_command, const t_execution_env *env) +{ + t_parse_tree_node *subnode; + + if (ft_vec_init(redirections, sizeof(t_redirection)) != success) + return (1); + subnode = ft_vec_access(&simple_command->children, 0); + if (is_token_type(subnode, "cmd_prefix")) + if (save_redirections_psfix(redirections, subnode, env)) + return (1); + subnode = ft_vec_access(&simple_command->children, simple_command->children.size - 1); + if (is_token_type(subnode, "cmd_suffix")) + if (save_redirections_psfix(redirections, subnode, env)) + return (1); + return (0); +} + +static const char space = ' '; + +int add_word(t_vec *exp_str, const char *word, const t_execution_env *env, int quote) +{ + size_t i; + char *var; + char *value; + const char *const_val; + int single_quoted; + int error; + + error = 0; + single_quoted = 0; + i = 0; + while (word[i]) + { + if (word[i] == '\'') + single_quoted = !single_quoted; + if (word[i] == '$' && !single_quoted && (ft_isalnum(word[i + 1]) || word[i + 1] == '_' || word[i + 1] == '?')) + { + ++i; + if (word[i] == '?') + { + ++i; + value = ft_itoa(env->ret_val); + } + else + { + var = get_var_name(word + i); + if (!var) + return (1); + i += ft_strlen(var); + const_val = get_env_var_value(env, var); + free(var); + if (!const_val) + continue; + value = ft_strdup(const_val); + } + if (!value) + return (1); + if (quote) + error = error || ft_vec_append(exp_str, "'") != success; + error = error || ft_vec_append_range(exp_str, value, ft_strlen(value)) != success; + if (quote) + error = error || ft_vec_append(exp_str, "'") != success; + free(value); + if (error) + return (1); + } + else + if (ft_vec_append(exp_str, word + (i++)) != success) + return (1); + } + if (ft_vec_append(exp_str, &space) != success) + return (1); + return (0); +} + +int expand_cmd(t_vec *exp_str, const t_parse_tree_node *node, const t_execution_env *env) +{ + size_t i; + const t_parse_tree_node *subnode; + + i = 0; + while (i < node->children.size) + { + subnode = ft_vec_caccess(&node->children, i); + if (is_token_type(subnode, "cmd_suffix")) + { + if (expand_cmd(exp_str, subnode, env)) + return (1); + } + else if (is_token_type(subnode, "WORD")) + if (add_word(exp_str, subnode->token.str, env, 0)) + return (1); + ++i; + } + return (0); +} + +size_t get_next_word_size(const char *str) +{ + size_t n; + char quote; + + quote = 0; + n = 0; + while (str[n]) + { + if (str[n] == ' ' && !quote) + break ; + if ((str[n] == '"' || str[n] == '\'')) + { + if (!quote) + quote = str[n]; + else if (quote == str[n]) + quote = 0; + } + ++n; + } + return (n); +} + +void unquote_field(char *field) +{ + size_t i; + char quote; + + quote = 0; + i = 0; + while (field && field[i]) + { + if (field[i] == '"' || field[i] == '\'') + { + if (!quote) + quote = field[i]; + else if (quote == field[i]) + quote = 0; + else + { + ++i; + continue ; + } + ft_memmove(field + i, field + i + 1, ft_strlen(field + i + 1) + 1); + } + else + ++i; + } + return ; +} + +void unquote(char **fields) +{ + size_t i; + + i = 0; + while (fields[i]) + { + unquote_field(fields[i]); + ++i; + } + return ; +} + +static const void *nullptr = NULL; + +char **quoted_split(const char *str) +{ + size_t i; + size_t n; + t_vec fields; + char *new_str; + + if (ft_vec_init(&fields, sizeof(char *)) != success) + return (NULL); + i = 0; + while (str[i]) + { + while (str[i] == ' ') + ++i; + n = get_next_word_size(str + i); + if (n == 0) + break ; + new_str = ft_strndup(str + i, n); + if (!new_str) + { + ft_vec_free(&fields, free); + return (NULL); + } + if (ft_vec_append(&fields, &new_str) != success) + { + ft_vec_free(&fields, free); + free(new_str); + return (NULL); + } + i += n; + } + if (ft_vec_append(&fields, &nullptr) != success) + { + ft_vec_free(&fields, free); + return (NULL); + } + return (fields.vec); +} + +static const char null_char = '\0'; + +char **expand(t_parse_tree_node *simple_command, const t_execution_env *env) +{ + size_t i; + char **fields; + t_vec expanded_str; + t_parse_tree_node *subnode; + + ft_vec_init(&expanded_str, sizeof(char)); + ft_vec_reserve(&expanded_str, 64); + i = 0; + while (i < simple_command->children.size) + { + subnode = ft_vec_access(&simple_command->children, i); + if (is_token_type(subnode, "cmd_name") + || is_token_type(subnode, "cmd_word") + || is_token_type(subnode, "cmd_suffix")) + if (expand_cmd(&expanded_str, subnode, env)) + { + ft_vec_free(&expanded_str, NULL); + return (NULL); + } + ++i; + } + if (ft_vec_append(&expanded_str, &null_char) != success) + { + ft_vec_free(&expanded_str, NULL); + return (NULL); + } + fields = quoted_split(expanded_str.vec); + ft_vec_free(&expanded_str, NULL); + unquote(fields); + return (fields); +} + +int assignments_to_env(const t_vec *assignments, t_execution_env *env) +{ + size_t i; + const char *var_line; + char *var_name; + + i = 0; + while (i < assignments->size) + { + var_line = *(char **)ft_vec_caccess(assignments, i); + var_name = get_var_name(var_line); + if (!var_name) + return (1); + if (set_env_var_value(env, var_name, var_line + ft_strlen(var_name) + 1)) + { + free(var_name); + return (1); + } + free(var_name); + ++i; + } + return (0); +} + +void free_split(char **fields) +{ + size_t i; + + i = 0; + while (fields[i]) + { + free(fields[i]); + ++i; + } + free(fields); + return ; +} + +int contains_path(const char *str) +{ + return (ft_strchr(str, '/') != NULL); +} + +int file_exists(const char *path) +{ + return (!access(path, F_OK)); +} + +int is_contained_in_dir(const char *exe_name, const char *dir_name) +{ + DIR *dir; + struct dirent *dir_entry; + + dir = opendir(dir_name); + if (!dir) + return (0); + dir_entry = readdir(dir); + while (dir_entry) + { + if (!ft_strcmp(dir_entry->d_name, exe_name)) + { + closedir(dir); + return (1); + } + dir_entry = readdir(dir); + } + closedir(dir); + return (0); +} + +char *find_exe(const char *exe_name, const t_execution_env *env) +{ + const char *path; + char **paths; + size_t i; + char *res; + + path = get_env_var_value(env, "PATH"); + if (!path) + return (NULL); + paths = ft_split(path, ":"); + if (!paths) + return (NULL); + res = NULL; + i = 0; + while (paths[i] && !res) + { + if (is_contained_in_dir(exe_name, paths[i])) + if (ft_strcat_alloc(&res, paths[i])) + if (ft_strcat_alloc(&res, "/")) + ft_strcat_alloc(&res, exe_name); + ++i; + } + free_split(paths); + return (res); +} + +int dup_pipes(const t_execution_env *env) +{ + if (dup2(env->stdin_fd, STDIN_FILENO) == -1) + return (1); + if (dup2(env->stdout_fd, STDOUT_FILENO) == -1) + return (1); + return (0); +} + +void close_pipes(const t_execution_env *env) +{ + close(env->stdin_fd); + close(env->stdout_fd); + return ; +} + +int dup_redirections(__attribute__((unused)) const t_vec *redirections) +{ + size_t i; + const t_redirection *redir; + + i = 0; + while (i < redirections->size) + { + redir = ft_vec_caccess(redirections, i); + dup2(redir->from_to_fds[1], redir->from_to_fds[0]); + close(redir->from_to_fds[1]); + ++i; + } + return (0); +} + +void close_redirections(const t_vec *redirections) +{ + size_t i; + const t_redirection *redir; + + i = 0; + while (i < redirections->size) + { + redir = ft_vec_caccess(redirections, i); + close(redir->from_to_fds[0]); + ++i; + } + return ; +} + +int add_exported(__attribute__((unused)) t_vec *assignments, __attribute__((unused)) const t_execution_env *env) +{ + size_t i; + char *var; + const t_vec *exported; + + exported = &env->vars->exported; + i = 0; + while (i < exported->size) + { + var = ft_strdup(*(char *const *)ft_vec_caccess(exported, i)); + if (ft_vec_append(assignments, &var) != success) // Should exported be overwritten? + return (1); + ++i; + } + return (0); +} + +int is_builtin(const char *str) +{ + if (!ft_strcmp(str, "cd")) + return (1); + if (!ft_strcmp(str, "echo")) + return (1); + if (!ft_strcmp(str, "pwd")) + return (1); + if (!ft_strcmp(str, "env")) + return (1); + if (!ft_strcmp(str, "export")) + return (1); + if (!ft_strcmp(str, "unset")) + return (1); + if (!ft_strcmp(str, "exit")) + return (1); + return (0); +} + +size_t count_fields(char **fields) +{ + size_t i; + + i = 0; + while (fields[i]) + ++i; + return (i); +} + +int save_std_filenos(int fds[3]) +{ + fds[0] = dup(STDIN_FILENO); + if (fds[0] < 0) + return (1); + fds[1] = dup(STDOUT_FILENO); + if (fds[1] < 0) + { + close(fds[0]); + return (1); + } + fds[2] = dup(STDERR_FILENO); + if (fds[2] < 0) + { + close(fds[0]); + close(fds[1]); + return (1); + } + return (0); +} + +int restore_std_filenos(int fds[3]) +{ + if (dup2(fds[0], STDIN_FILENO) == -1) + return (1); + if (dup2(fds[1], STDOUT_FILENO) == -1) + return (1); + if (dup2(fds[2], STDERR_FILENO) == -1) + return (1); + close(fds[0]); + close(fds[1]); + close(fds[2]); + return (0); +} + +int ex_builtin(char **fields, __attribute__((unused)) t_vec *assignments, __attribute__((unused)) const t_vec *redirections, t_execution_env *env) +{ + int fds[3]; + + save_std_filenos(fds); + dup_pipes(env); + dup_redirections(redirections); + if (!ft_strcmp(fields[0], "cd")) + env->last_builtin_ret_val = cd(count_fields(fields), fields, env); + else if (!ft_strcmp(fields[0], "echo")) + env->last_builtin_ret_val = echo(count_fields(fields), fields); + else if (!ft_strcmp(fields[0], "pwd")) + env->last_builtin_ret_val = pwd(); + else if (!ft_strcmp(fields[0], "env")) + env->last_builtin_ret_val = ft_env(count_fields(fields), env); + else if (!ft_strcmp(fields[0], "export")) + env->last_builtin_ret_val = export(count_fields(fields), fields, env); + else if (!ft_strcmp(fields[0], "unset")) + env->last_builtin_ret_val = unset(count_fields(fields), fields, env); + else if (!ft_strcmp(fields[0], "exit")) + env->last_builtin_ret_val = execute_exit(count_fields(fields), fields, env); + else + return (1); + env->last_was_builtin = 1; + close_redirections(redirections); + close_pipes(env); + restore_std_filenos(fds); + return (0); +} + +int ex_fields(char **fields, t_vec *assignments, const t_vec *redirections, t_execution_env *env) +{ + pid_t pid; + char *path; + + if (is_builtin(fields[0])) + return (ex_builtin(fields, assignments, redirections, env)); + env->last_was_builtin = 0; + path = NULL; + if (contains_path(fields[0]) && file_exists(fields[0])) + path = ft_strdup(fields[0]); + else if (!contains_path(fields[0])) + path = find_exe(fields[0], env); + if (!path) + return (1); + pid = fork(); + if (pid == 0) + { + dup_pipes(env); + dup_redirections(redirections); + add_exported(assignments, env); + ft_vec_append(assignments, nullptr); + execve(path, fields, assignments->vec); + exit(-1); + } + free(path); + if (pid > 0) + { + if (ft_vec_append(&env->child_pids, &pid) != success) + return (1); + } + else + return (1); + return (0); +} + +void close_redirection(void *v_redir) +{ + t_redirection *redir; + + redir = v_redir; + close(redir->from_to_fds[1]); + return ; +} + +int ex_simple_command(t_parse_tree_node *simple_command, t_execution_env *env) +{ + t_vec redirections; + t_vec assignments; + char **fields; + int res; + + res = save_redirections(&redirections, simple_command, env); + res = save_assignments(&assignments, simple_command, env) || res; + fields = NULL; + if (!res) + fields = expand(simple_command, env); + if (!fields || res) + { + ft_vec_free(&redirections, close_redirection); + ft_vec_free(&assignments, free); + return (1); + } + if (!*fields) + { + assignments_to_env(&assignments, env); + ft_vec_free(&redirections, close_redirection); + ft_vec_free(&assignments, free_str); + free_split(fields); + return (0); + } + res = ex_fields(fields, &assignments, &redirections, env); + ft_vec_free(&redirections, close_redirection); + ft_vec_free(&assignments, free_str); + free_split(fields); + return (res); +} + +t_ft_stat v_strcopy(void *v_dest, const void *v_src) +{ + char **dest; + const char *const *src; + + dest = v_dest; + src = v_src; + if (!*src) + { + *dest = NULL; + return (success); + } + *dest = ft_strdup(*src); + if (!*dest) + return (alloc_fail); + return (success); +} + +t_ft_stat v_copy_redir(void *v_dest, const void *v_src) +{ + t_redirection *dest; + const t_redirection *src; + + dest = v_dest; + src = v_src; + *dest = *src; + return (success); +} + +int ex_program(t_parse_tree_node *program, t_execution_env *env); + +int subshell(t_parse_tree_node *program, t_execution_env *env) +{ + int res; + int status; + pid_t pid; + + pid = fork(); + if (pid == 0) + { + env->subshell = 1; + res = ex_program(program, env); + env->exit = 1; + return (res); + } + else if (pid < 0) + return (1); + waitpid(pid, &status, 0); + if (!WIFEXITED(status)) + return (1); + env->ret_val = WEXITSTATUS(status); + return (0); +} + +int ex_command(t_parse_tree_node *command, t_execution_env *env) +{ + t_parse_tree_node *comp_command; + + if (env->exit) + return (0); + if (is_token_type(ft_vec_caccess(&command->children, 0), "simple_command")) + return (ex_simple_command(ft_vec_access(&command->children, 0), env)); + else + { + comp_command = ft_vec_access(&command->children, 0); + return (subshell(ft_vec_access(&comp_command->children, 1), env)); + } +} + +void killall(t_vec *child_pids, int sig_num) +{ + pid_t child_pid; + size_t i; + + i = 0; + while (i < child_pids->size) + { + child_pid = *(pid_t *)ft_vec_access(child_pids, i); + kill(child_pid, sig_num); + ++i; + } + return ; +} + +void wait_for_return(t_execution_env *env) +{ + pid_t last_pid; + int status; + + if (env->last_was_builtin) + env->ret_val = env->last_builtin_ret_val; + else + { + if (env->child_pids.size == 0) + return ; + last_pid = *(pid_t *)ft_vec_access(&env->child_pids, env->child_pids.size - 1); + waitpid(last_pid, &status, 0); + if (g_last_signal != 0) + killall(&env->child_pids, g_last_signal); + if (g_last_signal == 0) + if (WIFEXITED(status)) + env->ret_val = WEXITSTATUS(status); + } + ft_vec_free(&env->child_pids, NULL); + return ; +} + +int ex_pipeline(t_parse_tree_node *pipeline, t_execution_env *env, int depth) +{ + int pipe_fds[2]; + + if (g_last_signal != 0) + return (0); + if (pipeline->children.size == 1) + { + if (ex_command(ft_vec_access(&pipeline->children, 0), env)) + return (1); + } + else + { + if (pipe(pipe_fds)) + return (1); + ft_swap_int(&pipe_fds[1], &env->stdout_fd); + ex_pipeline(ft_vec_access(&pipeline->children, 0), env, depth + 1); + ft_swap_int(&pipe_fds[1], &env->stdout_fd); + close(pipe_fds[1]); + ft_swap_int(&pipe_fds[0], &env->stdin_fd); + ex_command(ft_vec_access(&pipeline->children, 2), env); + ft_swap_int(&pipe_fds[0], &env->stdin_fd); + close(pipe_fds[0]); + } + if (depth == 0) + wait_for_return(env); + return (0); +} + +int ex_program(t_parse_tree_node *program, t_execution_env *env) +{ + if (program->children.size == 1) + return (ex_pipeline(ft_vec_access(&program->children, 0), env, 0)); + if (ex_program(ft_vec_access(&program->children, 0), env)) + return (1); + if (is_token_type(ft_vec_caccess(&program->children, 1), "AND_IF")) + { + if (env->ret_val == 0) + return (ex_pipeline(ft_vec_access(&program->children, 2), env, 0)); + } + else + { + if (env->ret_val != 0) + return (ex_pipeline(ft_vec_access(&program->children, 2), env, 0)); + } + return (0); +} + +int execute(t_tree *parse_tree, t_execution_env *env) +{ + int res; + + res = ex_program(parse_tree, env); + if (g_last_signal != 0) + { + env->ret_val = 128 + g_last_signal; + g_last_signal = 0; + } + return (res); +} diff --git a/src/main.c b/src/main.c index 3e2f92b..9902951 100644 --- a/src/main.c +++ b/src/main.c @@ -6,7 +6,7 @@ /* By: ljiriste +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/04/26 13:11:47 by ljiriste #+# #+# */ -/* Updated: 2024/08/31 09:08:57 by ljiriste ### ########.fr */ +/* Updated: 2024/08/31 09:55:10 by ljiriste ### ########.fr */ /* */ /* ************************************************************************** */ @@ -19,12 +19,6 @@ #include #include -#ifndef NOLEAKS -# include // readline -# include // readline -# include // readline -#endif // NOLEAKS - volatile sig_atomic_t g_last_signal; void handler(int sig_num) @@ -33,48 +27,6 @@ void handler(int sig_num) return ; } -#ifndef NOLEAKS -void rl_handler(int sig_num) -{ - if (sig_num != SIGINT) - return ; - write(1, "\n", 1); - rl_on_new_line(); - rl_replace_line("", 0); - rl_redisplay(); - return ; -} - -void set_input_handler(void) -{ - struct sigaction sa; - - ft_memset(&sa, 0, sizeof(sa)); - sa.sa_handler = SIG_IGN; - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; - sigaction(SIGQUIT, &sa, NULL); - sa.sa_handler = rl_handler; - sigaction(SIGINT, &sa, NULL); - return ; -} -#else -void set_input_handler(void) -{ - struct sigaction sa; - - ft_memset(&sa, 0, sizeof(sa)); - sa.sa_handler = SIG_IGN; - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; - sigaction(SIGQUIT, &sa, NULL); - sa.sa_handler = handler; - sigaction(SIGINT, &sa, NULL); - return ; -} - -#endif // NOLEAKS - void set_execution_handler(void) { struct sigaction sa; @@ -131,17 +83,6 @@ void regenerate_terminal(void) return ; } -#ifdef NOLEAKS -void minishell_flush(void) -{ - struct termios termios; - - tcgetattr(STDIN_FILENO, &termios); - tcsetattr(STDIN_FILENO, TCSAFLUSH, &termios); - return ; -} -#endif // NOLEAKS - /* // This would be more portable than the main with 3 input args extern char **environ; diff --git a/src/noleaks_input.c b/src/noleaks_input.c new file mode 100644 index 0000000..d534f36 --- /dev/null +++ b/src/noleaks_input.c @@ -0,0 +1,74 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* noleaks_input.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: ljiriste +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/31 09:48:30 by ljiriste #+# #+# */ +/* Updated: 2024/08/31 10:03:56 by ljiriste ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" +#include "libft.h" +#include +#include +#include + +static void minishell_flush(void) +{ + struct termios termios; + + tcgetattr(STDIN_FILENO, &termios); + tcsetattr(STDIN_FILENO, TCSAFLUSH, &termios); + return ; +} + +char *get_line(void) +{ + char *cwd; + char *prompt; + char *line; + + cwd = getcwd(NULL, 0); + prompt = ft_strjoin(cwd, "$ "); + free(cwd); + ft_printf("%s", prompt); + free(prompt); + line = get_next_line(STDIN_FILENO); + if (!line) + { + ft_printf("\n"); + if (g_last_signal == SIGINT) + { + g_last_signal = 0; + minishell_flush(); + return (get_line()); + } + return (line); + } + if (line[ft_strlen(line) - 1] != '\n') + ft_printf("\n"); + return (line); +} + +void terminate_input(void) +{ + get_next_line(-1); + return ; +} + +void set_input_handler(void) +{ + struct sigaction sa; + + ft_memset(&sa, 0, sizeof(sa)); + sa.sa_handler = SIG_IGN; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sigaction(SIGQUIT, &sa, NULL); + sa.sa_handler = handler; + sigaction(SIGINT, &sa, NULL); + return ; +} diff --git a/src/input_method.c b/src/readline_input.c similarity index 55% rename from src/input_method.c rename to src/readline_input.c index ddb7681..d712583 100644 --- a/src/input_method.c +++ b/src/readline_input.c @@ -1,27 +1,34 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* input_method.c :+: :+: :+: */ +/* readline_input.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: ljiriste +#+ +:+ +#+ */ +/* By: ljiriste +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2024/08/27 14:22:08 by ljiriste #+# #+# */ -/* Updated: 2024/08/29 17:11:41 by ljiriste ### ########.fr */ +/* Created: 2024/08/31 09:46:31 by ljiriste #+# #+# */ +/* Updated: 2024/08/31 10:01:38 by ljiriste ### ########.fr */ /* */ /* ************************************************************************** */ -#include "minishell.h" -#include -#include // getcwd #include "libft.h" +#include +#include +#include -#ifndef NOLEAKS -# include // readline -# include // readline -# include // readline -#endif // NOLEAKS +#include +#include +#include -#ifndef NOLEAKS +static void rl_handler(int sig_num) +{ + if (sig_num != SIGINT) + return ; + write(1, "\n", 1); + rl_on_new_line(); + rl_replace_line("", 0); + rl_redisplay(); + return ; +} // A string "is_almost_empty" if it: // is a NULL pointer @@ -56,46 +63,22 @@ char *get_line(void) return (line); } -void terminate_input(void) -{ - rl_clear_history(); - return ; -} - -#else // NOLEAKS - -char *get_line(void) +void set_input_handler(void) { - char *cwd; - char *prompt; - char *line; + struct sigaction sa; - cwd = getcwd(NULL, 0); - prompt = ft_strjoin(cwd, "$ "); - free(cwd); - ft_printf("%s", prompt); - free(prompt); - line = get_next_line(STDIN_FILENO); - if (!line) - { - ft_printf("\n"); - if (g_last_signal == SIGINT) - { - g_last_signal = 0; - minishell_flush(); - return (get_line()); - } - return (line); - } - if (line[ft_strlen(line) - 1] != '\n') - ft_printf("\n"); - return (line); + ft_memset(&sa, 0, sizeof(sa)); + sa.sa_handler = SIG_IGN; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sigaction(SIGQUIT, &sa, NULL); + sa.sa_handler = rl_handler; + sigaction(SIGINT, &sa, NULL); + return ; } void terminate_input(void) { - get_next_line(-1); + rl_clear_history(); return ; } - -#endif // NOLEAKS -- 2.30.2