diff --git a/Makefile b/Makefile index 5e6a481b..f23eea6d 100644 --- a/Makefile +++ b/Makefile @@ -27,7 +27,7 @@ NAME = minishell # Comands COMPILER = cc DFLAGS = -g3 -gdwarf-2 -CFLAGS = -Wall -Wextra -Werror $(DFLAGS) +CFLAGS = -Wall -Wextra -Werror $(DFLAGS) -g -O0 AR = ar rcs RM = rm -rf MAKEFLAGS += --silent @@ -51,6 +51,7 @@ EXECUTE_DIR = $(SRC_DIR)/execute EXIT_STATUS_DIR = $(SRC_DIR)/exit_status TEST_DIR = $(SRC_DIR)/test SIGNALS_DIR = $(SRC_DIR)/signals +CHECK_TOKENISE_DIR = $(SRC_DIR)/check_tokenise INCLUDES = -I./inc \ -I $(LIB_DIR)/libft/inc \ @@ -73,6 +74,8 @@ BUILTINS_SOURCES = $(wildcard $(BUILTINS_DIR)/*.c) EXECUTE_SOURCES = $(wildcard $(EXECUTE_DIR)/*.c) EXIT_STATUS_SOURCES = $(wildcard $(EXIT_STATUS_DIR)/*.c) SIGNALS_SOURCES = $(wildcard $(SIGNALS_DIR)/*.c) +CHECK_TOKENISE_SOURCES = $(wildcard $(CHECK_TOKENISE_DIR)/*.c) + MAIN_TEST_SOURCE = $(wildcard $(TEST_DIR)/*.c) ENV_TEST_SOURCES = $(wildcard $(TEST_DIR)/env/*.c) @@ -94,7 +97,8 @@ SOURCES = $(MAIN_SOURCE) \ $(ENV_TEST_SOURCES) \ $(PIPE_TEST_SOURCES) \ $(REDIRECTION_SOURCES) \ - $(SIGNALS_SOURCES) + $(SIGNALS_SOURCES) \ + $(CHECK_TOKENISE) # Building BUILD_DIR = ./build MAIN_OBJECT = $(patsubst $(SRC_DIR)/%.c, $(BUILD_DIR)/src/%.o, $(MAIN_SOURCE)) @@ -113,6 +117,7 @@ SIGNALS_OBJECTS = $(patsubst $(SIGNALS_DIR)/%.c, $(BUILD_DIR)/src/signals/%.o MAIN_TEST_OBJECT = $(patsubst $(TEST_DIR)/%.c, $(BUILD_DIR)/src/test/%.o, $(MAIN_TEST_SOURCE)) ENV_TEST_OBJECTS = $(patsubst $(TEST_DIR)/env/%.c, $(BUILD_DIR)/src/test/env/%.o, $(ENV_TEST_SOURCES)) PIPE_TEST_OBJECTS = $(patsubst $(TEST_DIR)/pipe/%.c, $(BUILD_DIR)/src/test/pipe/%.o, $(PIPE_TEST_SOURCES)) +CHECK_TOKENISE_OBJECTS = $(patsubst $(CHECK_TOKENISE_DIR)/check_tokenise/%.c, $(BUILD_DIR)/src/check_tokenise/%.o, $(CHECK_TOKENISE_SOURCES)) OBJECTS = $(MAIN_OBJECT) \ $(APP_OBJECTS) \ @@ -127,7 +132,8 @@ OBJECTS = $(MAIN_OBJECT) \ $(PARSER_OBJECTS) \ $(PIPE_OBJECTS) \ $(REDIRECTION_OBJECTS) \ - $(SIGNALS_OBJECTS) + $(SIGNALS_OBJECTS) \ + $(CHECK_TOKENISE_OBJECTS) TEST_OBJECTS = $(APP_OBJECTS) \ $(ENV_OBJECTS) \ @@ -139,7 +145,8 @@ TEST_OBJECTS = $(APP_OBJECTS) \ $(PIPE_OBJECTS) \ $(MAIN_TEST_OBJECT) \ $(ENV_TEST_OBJECTS) \ - $(PIPE_TEST_OBJECTS) + $(PIPE_TEST_OBJECTS) \ + $(CHECK_TOKENISE_OBJECTS) # Processing all: $(NAME) @@ -234,6 +241,6 @@ test: $(TEST_OBJECTS) $(LIBFT) @./test valgrind: $(NAME) - @valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose --suppressions=readline.supp --log-file=valgrind-out.txt ./minishell + @valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --track-fds=yes --trace-children=yes --suppressions=readline.supp --num-callers=20 --log-file=valgrind-out.txt ./minishell .PHONY: all bonus clean fclean re test diff --git a/src/utils/.maxishell_history b/function_list.txt similarity index 100% rename from src/utils/.maxishell_history rename to function_list.txt diff --git a/inc/execute.h b/inc/execute.h index 35e202ad..fde2d67e 100644 --- a/inc/execute.h +++ b/inc/execute.h @@ -6,7 +6,7 @@ /* By: dmdemirk # include "shell.h" +// GLOBAL VAR +extern volatile sig_atomic_t g_heredoc_interrupted; + /* signals */ void signal_reset_prompt(int signo); void set_signals_interactive(void); void signal_print_newline(int signal); void sigquit_ignore(void); void set_signals_noninteractive(void); +void handle_sigint_heredoc(int signo); int ft_perror(char *str); + #endif diff --git a/inc/tokens.h b/inc/tokens.h index 2427e05f..d1b9fd4f 100644 --- a/inc/tokens.h +++ b/inc/tokens.h @@ -34,7 +34,8 @@ typedef enum e_token_type REDIR_IN, REDIR_OUT, REDIR_APPEND, - REDIR_HEREDOC + REDIR_HEREDOC, + NONE } t_token_type; typedef struct s_token @@ -73,18 +74,14 @@ int calc_stack_size(t_token *stack); char **list_to_array(t_token *head); void build_linked_list(t_token **tokens, char **argv); void handle_quotes(char **tokens, int *pos, char **input); -void handle_special_chars(char **str, t_token **tokens); -void handle_regular_chars(char **tokens, int *pos, char **input, \ - char *delim); +char *handle_special_chars(char *str, t_token **tokens); void skip_delimiters(char **input, char *delim); void reallocate_tokens(char ***tokens, int *bufsize); void parse_loop(char **input, char **tokens, int *pos, int *bufsize); char **parse_input(char *input); -// char *generate_prompt(void); char *generate_prompt(t_ms_data *data); void make_history(char *line); -void loop_cleanup(char *line, t_token *tokens, \ - char *prompt, t_ast *tree); +void loop_cleanup(t_loop_data *loop_data, t_token *tokens_head); void free_ms_data(t_ms_data *data); char *check_heredoc(char *line); char *heredoc(char *eof); @@ -92,7 +89,7 @@ void init_ms_data(t_ms_data *data, char **argv, char **envp); void initialise(int argc, char **argv); void execute_command(char **parsed_text, t_token **tokens); void print_maxishell(void); -int input_error_checks(const char *str); +int input_error_checks(t_loop_data *loop_data); t_token *tokenise(char *str); void print_tokens(t_token *tokens); t_ast *parse_tokens(t_token **tokens, t_ms_data *data); @@ -103,11 +100,11 @@ void free_all_tokens(t_token *tokens); t_token *new_token(char *value, t_token_type type); void append_token(t_token **tokens, t_token *new_token); int valid_operator(const char **str); -t_ast *new_ast_node(t_token_type type); +t_ast *new_ast_node(void); t_ast *create_redir(t_token **tokens, t_token *tmp, t_ms_data *data); int arg_len(t_token *current); void set_command_args(t_ast *command_node, t_token **tokens, \ - int arg_count); + int arg_count); t_ast *manage_commands(t_token **tokens, t_ms_data *data); t_ast *create_redir_node(t_token *token); int is_redir_node(t_token *tokens); @@ -119,5 +116,22 @@ void execute_tree(t_ast *node, t_ms_data *data); char *expand_env_and_loc_var(char *arg, t_ms_data *data); char *append_literal(char **start, char *processed_arg); char *process_argument(char *arg, t_ms_data *data); +char *expand_variable(char **start, t_ms_data *data); +void clear_history_file(void); +int is_in_single_quotes(char *arg); +void print_ast_args(t_ast *node); +void append_word_if_valid(char *start, char *str, t_token **tokens); +char *exit_status_adj(char *arg); +char *str_start_adj(char *arg); +char *tmp_adj(char *arg); +int cmd_arg_len(t_token *current); +char *exit_status_adj(char *arg); +int is_in_single_quotes(char *arg); +char *str_start_adj(char *arg); +char *tmp_adj(char *arg); +char *append_literal(char **start, char *processed_arg); +char *expand_variable(char **start, t_ms_data *data); +char *expand_env_and_loc_var(char *arg, t_ms_data *data); +void final_quote_removal(int arg_count, t_ast *command_node); -#endif +#endif \ No newline at end of file diff --git a/lib/libft/inc/libft.h b/lib/libft/inc/libft.h index 51746b0e..4d00422c 100644 --- a/lib/libft/inc/libft.h +++ b/lib/libft/inc/libft.h @@ -52,15 +52,19 @@ char *ft_strchr(const char *s, int c); char *ft_strcat(char *dest, char *src); char *ft_strrchr(const char *s, int c); char **ft_split(char const *s, char c); -char *ft_strcpy(char *dest, const char *src); char *ft_strndup(const char *s, size_t n); +char *ft_strjoin_free(char *s1, char *s2); +char *ft_strcpy(char *dest, const char *src); char *ft_strjoin(char const *s1, char const *s2); char *ft_strtrim(char const *s1, char const *set); char *ft_strstr(const char *big, const char *little); +char *ft_strcat_const(const char *dest, const char *src); char *ft_strmapi(char const *s, char (*f)(unsigned int, char)); char *ft_substr(char const *s, unsigned int start, size_t len); char *ft_strnstr(const char *haystack, const char *needle, size_t len); +void ft_free_2d_arr(char **arr); +void ft_print_2d_arr(char **arr); void ft_bzero(void *s, size_t n); void ft_putnbr_fd(int n, int fd); void ft_putchar_fd(char c, int fd); diff --git a/lib/libft/src/ft_free_2d_arr.c b/lib/libft/src/ft_free_2d_arr.c new file mode 100644 index 00000000..c12db523 --- /dev/null +++ b/lib/libft/src/ft_free_2d_arr.c @@ -0,0 +1,25 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_free_2d_arr.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: rmikhayl +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/09/09 19:37:13 by rmikhayl #+# #+# */ +/* Updated: 2024/09/09 19:37:16 by rmikhayl ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void ft_free_2d_arr(char **arr) +{ + int i; + + if (!arr) + return ; + i = -1; + while (arr[++i] != NULL) + free(arr[i]); + free(arr); +} diff --git a/lib/libft/src/ft_print_2d_arr.c b/lib/libft/src/ft_print_2d_arr.c new file mode 100644 index 00000000..3c60a042 --- /dev/null +++ b/lib/libft/src/ft_print_2d_arr.c @@ -0,0 +1,22 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_print_2d_arr.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: rmikhayl +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/09/09 19:37:13 by rmikhayl #+# #+# */ +/* Updated: 2024/09/09 19:37:16 by rmikhayl ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void ft_print_2d_arr(char **arr) +{ + int i; + + i = -1; + while (arr[++i] != NULL) + ft_printf("arr[%d]: %s at add: %p \n", i, arr[i], arr[i]); +} diff --git a/src/parser/tokeniser_helpers.c b/lib/libft/src/ft_strcat_const.c similarity index 51% rename from src/parser/tokeniser_helpers.c rename to lib/libft/src/ft_strcat_const.c index c4a63c70..97f438d8 100644 --- a/src/parser/tokeniser_helpers.c +++ b/lib/libft/src/ft_strcat_const.c @@ -1,46 +1,38 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* tokeniser_helpers.c :+: :+: :+: */ +/* ft_strcat_const.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: rocky +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2024/06/14 10:38:28 by rocky #+# #+# */ -/* Updated: 2024/06/14 10:38:30 by rocky ### ########.fr */ +/* Created: 2024/09/06 12:15:55 by rocky #+# #+# */ +/* Updated: 2024/09/06 12:15:59 by rocky ### ########.fr */ /* */ /* ************************************************************************** */ -#include "tokens.h" +#include "libft.h" -t_token *new_token(char *value, t_token_type type) +char *ft_strcat_const(const char *dest, const char *src) { - t_token *token; + int i; + int j; + char *result; - token = malloc(sizeof(t_token)); - if (!token) + result = malloc(sizeof(char) * (ft_strlen(dest) + ft_strlen(src) + 1)); + if (!result) return (NULL); - token->data = ft_strdup(value); - if (!token->data) + i = 0; + while (dest[i] != '\0') { - free(token); - return (NULL); + result[i] = dest[i]; + i++; } - token->type = type; - token->next = NULL; - return (token); -} - -void append_token(t_token **tokens, t_token *new_token) -{ - t_token *prev; - - if (!*tokens) - *tokens = new_token; - else + j = 0; + while (src[j] != '\0') { - prev = *tokens; - while (prev->next) - prev = prev->next; - prev->next = new_token; + result[i + j] = src[j]; + j++; } + result[i + j] = '\0'; + return (result); } diff --git a/src/parser/parser_utils.c b/lib/libft/src/ft_strjoin_free.c similarity index 59% rename from src/parser/parser_utils.c rename to lib/libft/src/ft_strjoin_free.c index 92d15d22..93981b0c 100644 --- a/src/parser/parser_utils.c +++ b/lib/libft/src/ft_strjoin_free.c @@ -1,22 +1,24 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* parser_utils.c :+: :+: :+: */ +/* ft_strjoin_free.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: dmdemirk +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2024/07/11 18:52:00 by dmdemirk #+# #+# */ -/* Updated: 2024/07/11 18:52:07 by dmdemirk ### ########.fr */ +/* Created: 2024/09/06 23:07:53 by rocky #+# #+# */ +/* Updated: 2024/09/06 23:07:55 by rocky ### ########.fr */ /* */ /* ************************************************************************** */ -#include "tokens.h" +#include "libft.h" -t_ast *parse_tokens(t_token **tokens, t_ms_data *data); - -t_ast *parse_tokens(t_token **tokens, t_ms_data *data) +char *ft_strjoin_free(char *s1, char *s2) { - if (!tokens || !*tokens) + char *result; + + if (!s1 || !s2) return (NULL); - return (manage_pipe(tokens, data)); + result = ft_strjoin(s1, s2); + free(s1); + return (result); } diff --git a/readline.supp b/readline.supp index 60bad3e6..851da425 100644 --- a/readline.supp +++ b/readline.supp @@ -9,4 +9,15 @@ Memcheck:Leak ... fun:add_history +} +{ + READLINE_IGNORE + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + fun:xmalloc + fun:readline_internal_teardown + fun:readline + fun:main_loop + fun:main } \ No newline at end of file diff --git a/src/builtins/cd.c b/src/builtins/cd.c index 382e4a4b..2926eda0 100644 --- a/src/builtins/cd.c +++ b/src/builtins/cd.c @@ -6,7 +6,7 @@ /* By: dmdemirk envp, "HOME"); target_dir = (char *)data->args[1]; if (!target_dir) target_dir = home_dir; if (chdir(target_dir) == -1) { + error_message = ft_strjoin("cd: ", target_dir); if (errno == EACCES) - exit_status_handler(data, PERMISSION_DENIED, \ - ft_strjoin("cd: ", target_dir)); + exit_status_handler(data, PERMISSION_DENIED, error_message); if (errno == ENOENT) - exit_status_handler(data, IS_DIRECTORY, \ - ft_strjoin("cd: ", target_dir)); + exit_status_handler(data, IS_DIRECTORY, error_message); + free(error_message); return (EXIT_FAILURE); } set_env(&data->envp, "OLDPWD", get_env(data->envp, "PWD")); diff --git a/src/builtins/env.c b/src/builtins/env.c index 7812a352..0eef6978 100644 --- a/src/builtins/env.c +++ b/src/builtins/env.c @@ -34,7 +34,6 @@ void print_env_stack(t_env *envp) int builtin_env(t_ms_data *data) { - ft_printf("\nbuiltin_env\n"); if (ft_strcmp(data->args[0], "env") == 0 && data->args[1] == NULL) print_env_stack(data->envp); else diff --git a/src/builtins/exit.c b/src/builtins/exit.c index 6b9e7a2c..3f216ec8 100644 --- a/src/builtins/exit.c +++ b/src/builtins/exit.c @@ -6,7 +6,7 @@ /* By: dmdemirk #include "env.h" #include "exit_status.h" +#include "tokens.h" /* Functionality: @@ -24,6 +25,11 @@ - Exit with the exit status */ +void clear_history_file(void) +{ + remove(HISTORY_PATH); +} + void handle_numeric_error(t_ms_data *data, const char *arg) { exit_status_handler(data, NUMERIC_REQUIRED, ft_strjoin("exit: ", arg)); @@ -38,9 +44,15 @@ void handle_too_many_args_error(t_ms_data *data) void handle_exit(t_ms_data *data, int status) { + char *exit_status_str; + ft_putendl_fd("exit", STDOUT_FILENO); data->exit_status = status; - set_shell_var(&data->shell_variables, "?", ft_itoa(data->exit_status)); + exit_status_str = ft_itoa(data->exit_status); + set_shell_var(&data->shell_variables, "?", exit_status_str); + free(exit_status_str); + clear_history_file(); + free_ms_data(data); exit(status); } diff --git a/src/builtins/export.c b/src/builtins/export.c index 40b33b39..ce2e0628 100644 --- a/src/builtins/export.c +++ b/src/builtins/export.c @@ -6,7 +6,7 @@ /* By: dmdemirk value, "")) - printf("declare -x %s\n", curr_node->key); + ft_printf("declare -x %s\n", curr_node->key); else - printf("declare -x %s=\"%s\"\n", curr_node->key, curr_node->value); + ft_printf("declare -x %s=\"%s\"\n", curr_node->key, curr_node->value); curr_node = curr_node->next; } } @@ -83,6 +83,7 @@ static void add_env(t_ms_data *data) key = ft_strcdup(curr_arg, '='); set_env(&data->envp, key, \ ft_strchr(curr_arg, '=') + 1); + free(key); } else { diff --git a/src/parser/input_checker.c b/src/check_tokenise/input_checker.c similarity index 71% rename from src/parser/input_checker.c rename to src/check_tokenise/input_checker.c index fe90bcb7..310ced64 100644 --- a/src/parser/input_checker.c +++ b/src/check_tokenise/input_checker.c @@ -12,42 +12,39 @@ #include "tokens.h" -int check_operators_loop(const char **str, int *single_quotes, \ - int *double_quotes, int *cmd_flag) +void free_op_strings(t_loop_data *data, char *tail, char *new) { - if (**str == '\'') - (*single_quotes)++; - if (**str == '\"') - (*double_quotes)++; - if (**str == '|' && !(*single_quotes % 2) && !(*double_quotes % 2)) - { - if (*cmd_flag) - return (1); - *cmd_flag = 1; - } - else if (ft_strchr(" \t\n\r\v\f", **str) != NULL) - *cmd_flag = 0; - (*str)++; - return (0); + free(data->trimmed_input); + free(new); + free(tail); } -int check_operators(const char *str) +int check_operators(t_loop_data *loop_data) { - int single_quotes; - int double_quotes; - int cmd_flag; + char *input; + char *tail; + char *new_input; + char *final_input; - single_quotes = 0; - double_quotes = 0; - cmd_flag = 0; - if (*str == '&' || *str == '|') - return (1); - while (*str) - if (check_operators_loop(&str, &single_quotes, \ - &double_quotes, &cmd_flag) == 1) - return (1); - if (cmd_flag) + input = loop_data->trimmed_input; + if (*input == '&' || *input == '|') return (1); + while (*input) + { + if (*input == '|' && *(input + 1) == '\0') + { + tail = readline("> "); + if (tail == NULL) + break ; + new_input = ft_strcat_const(loop_data->trimmed_input, " "); + final_input = ft_strcat_const(new_input, tail); + free_op_strings(loop_data, tail, new_input); + loop_data->trimmed_input = final_input; + free(final_input); + break ; + } + input++; + } return (0); } @@ -96,11 +93,13 @@ int check_open_quotes(const char *str) return (single_quote_open || double_quote_open); } -int input_error_checks(const char *str) +int input_error_checks(t_loop_data *loop_data) { + const char *str = loop_data->trimmed_input; + if (check_redirections(str)) ft_printf("Input error: invalid redirection.\n"); - else if (check_operators(str)) + else if (check_operators(loop_data)) ft_printf("Input error: invalid operator.\n"); else if (check_open_quotes(str)) ft_printf("Input error: open quote.\n"); diff --git a/src/parser/input_checker_helpers.c b/src/check_tokenise/input_checker_helpers.c similarity index 100% rename from src/parser/input_checker_helpers.c rename to src/check_tokenise/input_checker_helpers.c diff --git a/src/parser/tokeniser.c b/src/check_tokenise/tokeniser.c similarity index 53% rename from src/parser/tokeniser.c rename to src/check_tokenise/tokeniser.c index bcfcfcf8..2d416cd2 100644 --- a/src/parser/tokeniser.c +++ b/src/check_tokenise/tokeniser.c @@ -6,110 +6,119 @@ /* By: rocky +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/06/12 15:00:23 by rocky #+# #+# */ -/* Updated: 2024/06/12 15:00:25 by rocky ### ########.fr */ +/* Updated: 2024/09/09 15:48:26 by dmdemirk ### ########.fr */ /* */ /* ************************************************************************** */ #include "tokens.h" #include -void handle_special_chars(char **str, t_token **tokens) +t_token *tokenise(char *str); +char *handle_special_chars(char *str, t_token **tokens); +t_token *new_token(char *value, t_token_type type); +void append_token(t_token **tokens, t_token *new_token); +char *handle_phrase(char *str, t_token **tokens); + +t_token *tokenise(char *str) { - if (**str == '<') + t_token *tokens; + + tokens = NULL; + while (*str) { - if (*(*str + 1) == '<') + while (*str && ft_strchr(" \t\n\r\v\f", *str) != NULL) + str++; + if (ft_strchr("<|>", *str) != NULL) + str = handle_special_chars(str, &tokens); + else + str = handle_phrase(str, &tokens); + } + return (tokens); +} + +char *handle_special_chars(char *str, t_token **tokens) +{ + if (*str == '<') + { + if (*(str + 1) == '<') { append_token(tokens, new_token("<<", REDIR_HEREDOC)); - (*str)++; + (str)++; } else append_token(tokens, new_token("<", REDIR_IN)); } - else if (**str == '>') + else if (*str == '>') { - if (*(*str + 1) == '>') + if (*(str + 1) == '>') { append_token(tokens, new_token(">>", REDIR_APPEND)); - (*str)++; + (str)++; } else append_token(tokens, new_token(">", REDIR_OUT)); } - else if (**str == '|') + else if (*str == '|') append_token(tokens, new_token("|", PIPE)); - (*str)++; + (str)++; + return (str); } -void append_phrase_if_valid(char **start, char **str, t_token **tokens) +t_token *new_token(char *value, t_token_type type) { - char *phrase; + t_token *token; - if (*str > *start) + token = malloc(sizeof(t_token)); + if (!token) + return (NULL); + token->data = ft_strdup(value); + if (!token->data) { - phrase = ft_strndup(*start, *str - *start); - if (phrase) - { - append_token(tokens, new_token(phrase, PHRASE)); - free(phrase); - } - else - ft_printf("Error: unable to allocate memory for token\n"); + free(token); + return (NULL); } + token->type = type; + token->next = NULL; + return (token); } -void handle_phrase(char **str, t_token **tokens) +void append_token(t_token **tokens, t_token *new_token) +{ + t_token *curr; + + if (!*tokens) + *tokens = new_token; + else + { + curr = *tokens; + while (curr->next) + curr = curr->next; + curr->next = new_token; + } +} + +char *handle_phrase(char *str, t_token **tokens) { char *start; char quote_flag; char quote_type; - start = *str; + start = str; quote_flag = 0; quote_type = 0; - while (**str) + while (*str) { - if (!quote_flag && (**str == '\'' || **str == '\"')) + if (!quote_flag && (*str == '\'' || *str == '\"')) { quote_flag = 1; - quote_type = **str; + quote_type = *str; } - else if (quote_flag && **str == quote_type) + else if (quote_flag && *str == quote_type) quote_flag = 0; - if (!quote_flag && ft_strchr(" \t\n\r\v\f<|>", **str) != NULL) + if (!quote_flag && ft_strchr(" \t\n\r\v\f<|>", *str) != NULL) break ; - (*str)++; - } - append_phrase_if_valid(&start, str, tokens); -} - -void print_tokens(t_token *tokens) -{ - t_token *token; - int i; - - i = 0; - token = tokens; - while (token != NULL) - { - ft_printf("input[%d] -> %s \n", i, token->data); - token = token->next; - i++; - } -} - -t_token *tokenise(char *str) -{ - t_token *tokens; - - tokens = NULL; - while (*str) - { - while (*str && ft_strchr(" \t\n\r\v\f", *str) != NULL) - str++; - if (ft_strchr("<|>", *str) != NULL) - handle_special_chars(&str, &tokens); - else - handle_phrase(&str, &tokens); + str++; } - return (tokens); + append_word_if_valid(start, str, tokens); + return (str); } diff --git a/src/check_tokenise/tokeniser_helpers.c b/src/check_tokenise/tokeniser_helpers.c new file mode 100644 index 00000000..1eaf228d --- /dev/null +++ b/src/check_tokenise/tokeniser_helpers.c @@ -0,0 +1,62 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* tokeniser_helpers.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: rocky +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/14 10:38:28 by rocky #+# #+# */ +/* Updated: 2024/09/09 15:47:48 by dmdemirk ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "tokens.h" + +void print_tokens(t_token *tokens); +void print_ast_args(t_ast *node); +void append_word_if_valid(char *start, char *str, t_token **tokens); + +void print_tokens(t_token *tokens) +{ + t_token *token; + int i; + + i = 0; + token = tokens; + while (token != NULL) + { + ft_printf("input[%d] -> %s at add: %p\n", \ + i, token->data, &token->data); + token = token->next; + i++; + } +} + +void print_ast_args(t_ast *node) +{ + int i; + + i = 0; + while (node->args[i] != NULL) + { + ft_printf("ast arg[%d] -> %s \n", i, node->args[i]); + i++; + } +} + +void append_word_if_valid(char *start, char *str, t_token **tokens) +{ + char *word; + + if (str > start) + { + word = ft_strndup(start, str - start); + if (word) + { + append_token(tokens, new_token(word, PHRASE)); + free(word); + } + else + ft_printf("Error: unable to allocate memory for token\n"); + } +} diff --git a/src/env/env.c b/src/env/env.c index cf2bf419..e1f269c3 100644 --- a/src/env/env.c +++ b/src/env/env.c @@ -6,7 +6,7 @@ /* By: dmdemirk key = ft_strdup(key); - new_node->value = ft_strdup(value); - free(key); + eq_pos = ft_strchr(line, '='); + if (!eq_pos) + return ; + new_node->key = ft_strndup(line, eq_pos - line); + new_node->value = ft_strdup(eq_pos + 1); new_node->next = NULL; - if (*data_envp == NULL) - { + if (!*data_envp) *data_envp = new_node; - return ; + else + { + curr = *data_envp; + while (curr->next) + curr = curr->next; + curr->next = new_node; } - curr_node = *data_envp; - while (curr_node->next != NULL) - curr_node = curr_node->next; - curr_node->next = new_node; } char *get_env(t_env *envp, const char *key) @@ -70,18 +69,12 @@ char *get_env(t_env *envp, const char *key) } return (NULL); } -/* -todo: -minishell`set_env(env=0x000000016fdfed50, key="PWD", -value="/Users/dimadem/Documents/GitHub/minishell/inc") at env.c:84:4 - */ void set_env(t_env **env, const char *key, const char *value) { t_env *current; t_env *new_env; - printf("KEY -> %s\nVALUE -> %s\n", key, value); current = *env; while (current) { diff --git a/src/execute/execute.c b/src/execute/execute.c index 65b947cf..c700aa88 100644 --- a/src/execute/execute.c +++ b/src/execute/execute.c @@ -6,7 +6,7 @@ /* By: dmdemirk std_in == -1) - data->std_in = dup(STDIN_FILENO); - if (data->std_out == -1) - data->std_out = dup(STDOUT_FILENO); + handle_std_io(&data->std_in, STDIN_FILENO); + handle_std_io(&data->std_out, STDOUT_FILENO); pid = fork(); if (pid == -1) ft_perror("fork"); if (pid == 0) { - if (data->std_in != -1) - dup2(data->std_in, STDIN_FILENO); - if (data->std_out != -1) - dup2(data->std_out, STDOUT_FILENO); + handle_std_io(&data->std_in, STDIN_FILENO); + handle_std_io(&data->std_out, STDOUT_FILENO); close_fds(data->std_in, data->std_out); - if (execve(ft_find_path(data->args[0], data->envp), \ - data->args, env_to_array(data->envp)) == -1) - ft_perror("minishell"); + signal_handler(); + exec_path = ft_find_path(data->args[0], data->envp); + handle_exec_errors(exec_path, data); } close_fds(data->std_in, data->std_out); waitpid(pid, &data->exit_status, 0); + if (WIFSIGNALED(data->exit_status) \ + && WTERMSIG(data->exit_status) == SIGQUIT) + ft_printf("\n"); return (EXIT_SUCCESS); } + +static void handle_exec_errors(char *exec_path, t_ms_data *data) +{ + if (!exec_path) + { + ft_putstr_fd("maxishell: command not found\n", STDERR_FILENO); + exit(EXIT_FAILURE); + } + if (!data->args || !data->args[0] || !data->envp) + { + ft_putstr_fd("maxishell: invalid \ + arguments or environment\n", STDERR_FILENO); + exit(EXIT_FAILURE); + } + if (execve(exec_path, data->args, env_to_array(data->envp)) == -1) + { + exit_status_handler(data, IS_DIRECTORY, "maxishell: "); + exit(IS_DIRECTORY); + } +} + +static void signal_handler(void) +{ + struct sigaction a; + + ft_memset(&a, 0, sizeof(struct sigaction)); + sigemptyset(&a.sa_mask); + a.sa_handler = SIG_DFL; + a.sa_flags = 0; + sigaction(SIGQUIT, &a, NULL); +} diff --git a/src/execute/utils_0.c b/src/execute/utils_0.c index 4402fa00..38a5b1e6 100644 --- a/src/execute/utils_0.c +++ b/src/execute/utils_0.c @@ -6,7 +6,7 @@ /* By: dmdemirk std_out = -1; } } + +void handle_std_io(int *std_io, int std_fileno) +{ + if (*std_io == -1) + *std_io = dup(std_fileno); + else + dup2(*std_io, std_fileno); +} diff --git a/src/execute/utils_1.c b/src/execute/utils_1.c index 54e2fee7..5b31be34 100644 --- a/src/execute/utils_1.c +++ b/src/execute/utils_1.c @@ -6,7 +6,7 @@ /* By: dmdemirk #include "libft.h" -int ft_perror(char *str); -int ft_isnumber(char *str); - -/** - - @brief return error message and exit - - - - @param str paste the error message - - @return int return status: - - - 1: ERROR - */ - int ft_perror(char *str) { perror (str); diff --git a/src/main.c b/src/main.c index f91ffcae..ed8da827 100644 --- a/src/main.c +++ b/src/main.c @@ -6,7 +6,7 @@ /* By: rmikhayl +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/06/05 13:23:26 by rmikhayl #+# #+# */ -/* Updated: 2024/07/18 16:02:15 by dmdemirk ### ########.fr */ +/* Updated: 2024/09/09 13:27:44 by dmdemirk ### ########.fr */ /* */ /* ************************************************************************** */ @@ -16,34 +16,42 @@ #include "pipe.h" #include "signals.h" -int status_handler(int status, t_loop_data *loop_data) +static int status_handler(int status, \ + t_loop_data *loop_data, t_token *token_head); +static void process_ast_and_io(t_ms_data *data, \ + t_loop_data *loop_data, t_token *tokens_head); +static void main_loop(t_ms_data *data, t_loop_data *loop_data); +int main(int argc, char **argv, char **envp); + +static int status_handler(int status, \ + t_loop_data *loop_data, t_token *tokens_head) { if (status == WAIT_NEXT_COMMAND) { - loop_cleanup(loop_data->trimmed_input, loop_data->tokens, \ - loop_data->prompt, loop_data->tree); + loop_cleanup(loop_data, tokens_head); return (0); } return (1); } -void process_ast_and_io(t_ms_data *data, t_loop_data *loop_data) +static void process_ast_and_io(t_ms_data *data, \ + t_loop_data *loop_data, t_token *tokens_head) { int status; - print_ast_root(loop_data->tree); status = execute_ast(loop_data->tree, data); shell_variable_update(data, status); - if (status_handler(status, loop_data)) + if (status_handler(status, loop_data, tokens_head)) { handle_io_fd(data); - loop_cleanup(loop_data->trimmed_input, loop_data->tokens, \ - loop_data->prompt, loop_data->tree); + loop_cleanup(loop_data, tokens_head); } } -void main_loop(t_ms_data *data, t_loop_data *loop_data) +static void main_loop(t_ms_data *data, t_loop_data *loop_data) { + t_token *tokens_start; + while (1) { loop_data->prompt = generate_prompt(data); @@ -57,12 +65,14 @@ void main_loop(t_ms_data *data, t_loop_data *loop_data) } make_history(loop_data->input); loop_data->trimmed_input = trim_input(loop_data->input); - if (input_error_checks(loop_data->trimmed_input)) + if (input_error_checks(loop_data)) continue ; loop_data->tokens = tokenise(loop_data->trimmed_input); + tokens_start = loop_data->tokens; loop_data->tree = parse_tokens(&loop_data->tokens, data); - process_ast_and_io(data, loop_data); + process_ast_and_io(data, loop_data, tokens_start); } + clear_history_file(); free(loop_data->prompt); } @@ -76,5 +86,6 @@ int main(int argc, char **argv, char **envp) initialise(argc, argv); main_loop(&data, &loop_data); free_ms_data(&data); + clear_history_file(); return (0); } diff --git a/src/parser/parser.c b/src/parser/AST.c similarity index 71% rename from src/parser/parser.c rename to src/parser/AST.c index 5c4a4917..346b85d5 100644 --- a/src/parser/parser.c +++ b/src/parser/AST.c @@ -1,53 +1,21 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* parser.c :+: :+: :+: */ +/* AST.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: rocky +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/06/12 19:35:45 by rocky #+# #+# */ -/* Updated: 2024/08/28 20:11:50 by rocky ### ########.fr */ +/* Updated: 2024/09/09 16:18:58 by dmdemirk ### ########.fr */ /* */ /* ************************************************************************** */ #include "tokens.h" +t_ast *manage_redirs(t_token **tokens, t_ms_data *data); t_ast *create_redir_node(t_token *token); int is_redir_node(t_token *tokens); -t_ast *manage_redirs(t_token **tokens, t_ms_data *data); -t_ast *manage_pipe(t_token **tokens, t_ms_data *data); - -t_ast *create_redir_node(t_token *token) -{ - t_ast *node; - - node = malloc(sizeof(t_ast)); - if (!node) - return (NULL); - node->type = token->type; - node->args = malloc(sizeof(char *) * 2); - if (!node->args) - { - free(node); - return (NULL); - } - node->args[0] = token->data; - node->args[1] = NULL; - node->left = NULL; - node->right = NULL; - free(token); - return (node); -} - -int is_redir_node(t_token *tokens) -{ - if (tokens->type == REDIR_IN - || tokens->type == REDIR_OUT - || tokens->type == REDIR_APPEND - || tokens->type == REDIR_HEREDOC) - return (1); - return (0); -} +t_ast *new_ast_node(void); t_ast *manage_redirs(t_token **tokens, t_ms_data *data) { @@ -77,30 +45,57 @@ t_ast *manage_redirs(t_token **tokens, t_ms_data *data) return (command_node); } -t_ast *manage_pipe(t_token **tokens, t_ms_data *data) +void set_command_args(t_ast *command_node, t_token **tokens, int arg_count) { - t_token *tmp; - t_token *next_token; - t_ast *pipe_node; + int i; - tmp = *tokens; - while (*tokens && (*tokens)->next) + i = 0; + while (i < arg_count) { - next_token = (*tokens)->next; - if ((*tokens)->next->type == PIPE) - { - pipe_node = new_ast_node((*tokens)->next->type); - (*tokens)->next = NULL; - pipe_node->left = manage_redirs(&tmp, data); - if (next_token->next == NULL) - pipe_node->right = NULL; - else - pipe_node->right = manage_pipe(&(next_token->next), data); - free(next_token->data); - free(next_token); - return (pipe_node); - } - *tokens = next_token; + command_node->args[i] = ft_strdup((*tokens)->data); + *tokens = (*tokens)->next; + i++; } - return (manage_redirs(&tmp, data)); + command_node->args[arg_count] = NULL; +} + +t_ast *create_redir_node(t_token *token) +{ + t_ast *node; + + node = new_ast_node(); + node->type = token->type; + node->args = malloc(sizeof(char *) * 2); + if (!node->args) + { + free(node); + return (NULL); + } + node->args[0] = ft_strdup(token->data); + node->args[1] = NULL; + return (node); +} + +int is_redir_node(t_token *tokens) +{ + if (tokens->type == REDIR_IN + || tokens->type == REDIR_OUT + || tokens->type == REDIR_APPEND + || tokens->type == REDIR_HEREDOC) + return (1); + return (0); +} + +t_ast *new_ast_node(void) +{ + t_ast *node; + + node = malloc(sizeof(t_ast)); + if (!node) + return (NULL); + node->type = NONE; + node->args = NULL; + node->left = NULL; + node->right = NULL; + return (node); } diff --git a/src/parser/AST_utils.c b/src/parser/AST_utils.c new file mode 100644 index 00000000..2ac631ee --- /dev/null +++ b/src/parser/AST_utils.c @@ -0,0 +1,99 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* AST_utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: dmdemirk type = next_token->type; + pipe_node->args = malloc(sizeof(char *) * 2); + if (!pipe_node->args) + { + free(pipe_node); + return (NULL); + } + pipe_node->args[0] = ft_strdup(next_token->data); + pipe_node->args[1] = NULL; + pipe_node->left = manage_redirs(&tmp, data); + *tokens = next_token->next; + if (next_token->next) + pipe_node->right = manage_pipe(tokens, data); + else + pipe_node->right = NULL; + return (pipe_node); +} + +t_ast *manage_pipe(t_token **tokens, t_ms_data *data) +{ + t_token *tmp; + t_token *next_token; + + tmp = *tokens; + while (*tokens && (*tokens)->next) + { + next_token = (*tokens)->next; + if (next_token->type == PIPE) + return (create_pipe_node(next_token, tokens, data, tmp)); + *tokens = next_token; + } + return (manage_redirs(&tmp, data)); +} + +t_ast *manage_commands(t_token **tokens, t_ms_data *data) +{ + t_ast *command_node; + int cmd_arg_count; + + command_node = new_ast_node(); + command_node->type = PHRASE; + cmd_arg_count = cmd_arg_len(*tokens); + command_node->args = malloc(sizeof(char *) * (cmd_arg_count + 1)); + if (!command_node->args) + return (NULL); + set_command_args(command_node, tokens, cmd_arg_count); + post_process_command_args(command_node, cmd_arg_count, data); + return (command_node); +} + +int cmd_arg_len(t_token *current) +{ + int i; + + i = 0; + while (current && current->type == PHRASE) + { + i++; + current = current->next; + } + return (i); +} diff --git a/src/parser/loc_env_var_handler.c b/src/parser/loc_env_var_handler.c new file mode 100644 index 00000000..24ff5f9b --- /dev/null +++ b/src/parser/loc_env_var_handler.c @@ -0,0 +1,107 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* loc_env_var_handler.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: rmikhayl +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/09/04 16:46:53 by rmikhayl #+# #+# */ +/* Updated: 2024/09/09 16:19:56 by dmdemirk ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include + +void handle_local_vars(t_ms_data *data, char *arg); +char *process_argument(char *arg, t_ms_data *data); + +void post_process_command_args(t_ast *command_node, int arg_count, \ + t_ms_data *data) +{ + int i; + char *processed_arg; + + i = 0; + while (i < arg_count) + { + if (!is_in_single_quotes(command_node->args[i])) + { + handle_local_vars(data, command_node->args[i]); + processed_arg = process_argument(command_node->args[i], data); + } + else + { + processed_arg = ft_substr(command_node->args[i], 1, + ft_strlen(command_node->args[i]) - 2); + } + free(command_node->args[i]); + command_node->args[i] = ft_strdup(processed_arg); + free(processed_arg); + i++; + } + final_quote_removal(arg_count, command_node); +} + +void handle_local_vars(t_ms_data *data, char *arg) +{ + char *p; + int valid_var; + + p = arg; + valid_var = 1; + if (arg[0] != '=' && ft_strchr(arg, '=')) + { + while (p < ft_strchr(arg, '=')) + { + if (!ft_isalnum(*p++)) + { + valid_var = 0; + break ; + } + } + if (valid_var) + handle_add_set_shell_variable(&data->shell_variables, arg); + } +} + +char *append_expanded_var(char *processed_arg, char *tmp_ad, \ + char *expanded_var) +{ + char *tmp; + char *tmp_2; + + tmp = ft_strjoin_free(processed_arg, expanded_var); + tmp_ad = tmp_adj(tmp); + free(expanded_var); + tmp_2 = ft_strdup(tmp_ad); + free(tmp_ad); + return (tmp_2); +} + +char *process_argument(char *arg, t_ms_data *data) +{ + char *start; + char *processed_arg; + char *tmp_ad; + char *expanded_var; + + tmp_ad = NULL; + processed_arg = ft_strdup(""); + start = arg; + while (*start != '\0') + { + if (*start == '$') + { + expanded_var = expand_variable(&start, data); + if (expanded_var != NULL) + { + processed_arg = append_expanded_var(processed_arg, \ + tmp_ad, expanded_var); + free(tmp_ad); + } + } + else + processed_arg = append_literal(&start, processed_arg); + } + return (processed_arg); +} diff --git a/src/parser/loc_env_var_handler_heredoc.c b/src/parser/loc_env_var_handler_heredoc.c new file mode 100644 index 00000000..b9a6c4e9 --- /dev/null +++ b/src/parser/loc_env_var_handler_heredoc.c @@ -0,0 +1,114 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* loc_env_var_handler_heredoc.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: dmdemirk +#include +#include "signals.h" + +static char *assemble_result(char **tokens, size_t result_len); +char *token_adj(char *arg); +char *finalize_token(char *tmp_token, char *orig_token); +size_t process_single_token(char **token, t_ms_data *data); +size_t process_tokens(char **tokens, t_ms_data *data); + +char *process_and_reassemble(char *line, t_ms_data *data) +{ + char **tokens; + size_t result_len; + char *result; + + tokens = ft_split(line, ' '); + free(line); + if (!tokens) + return (NULL); + result_len = process_tokens(tokens, data); + result = assemble_result(tokens, result_len); + ft_free_2d_arr(tokens); + return (result); +} + +size_t process_tokens(char **tokens, t_ms_data *data) +{ + int i; + size_t result_len; + + result_len = 0; + i = 0; + while (tokens[i]) + { + result_len += process_single_token(&tokens[i], data); + i++; + } + return (result_len); +} + +size_t process_single_token(char **token, t_ms_data *data) +{ + char *orig_token; + char *tmp_token; + char *new_token; + size_t new_len; + + orig_token = *token; + tmp_token = expand_variable(token, data); + new_token = finalize_token(tmp_token, orig_token); + *token = new_token; + free(orig_token); + new_len = ft_strlen(new_token) + 1; + return (new_len); +} + +char *finalize_token(char *tmp_token, char *orig_token) +{ + char *processed_token; + char *new_token; + + if (tmp_token) + { + processed_token = token_adj(tmp_token); + if (processed_token != tmp_token) + { + new_token = ft_strdup(processed_token); + free(tmp_token); + } + else + new_token = tmp_token; + free(processed_token); + } + else + new_token = ft_strdup(orig_token); + return (new_token); +} + +static char *assemble_result(char **tokens, size_t result_len) +{ + char *result; + int i; + + result = malloc(result_len + 1); + if (!result) + return (NULL); + *result = '\0'; + i = 0; + while (tokens[i]) + { + ft_strcat(result, tokens[i]); + if (tokens[i + 1]) + ft_strcat(result, " "); + i++; + } + return (result); +} diff --git a/src/parser/loc_env_var_handler_heredoc_utils.c b/src/parser/loc_env_var_handler_heredoc_utils.c new file mode 100644 index 00000000..1a2e5c3b --- /dev/null +++ b/src/parser/loc_env_var_handler_heredoc_utils.c @@ -0,0 +1,48 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* loc_env_var_handler_heredoc_utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: rmikhayl +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/09/10 01:04:20 by rmikhayl #+# #+# */ +/* Updated: 2024/09/10 01:04:22 by rmikhayl ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "shell.h" +#include "tokens.h" +#include "redirection.h" +#include "execute.h" +#include +#include +#include "signals.h" + +char *token_adj(char *arg) +{ + char *ptr; + char *new_arg; + + if (*arg == '\"') + { + ptr = arg + 1; + while (*ptr && *ptr != '\"') + { + if (!ft_isdigit(*ptr)) + return (ft_strdup(arg)); + ptr++; + } + if (*ptr == '\0') + { + new_arg = malloc(ft_strlen(arg) + 2); + if (!new_arg) + return (NULL); + ft_strcpy(new_arg, arg); + ft_strcat(new_arg, "\""); + return (new_arg); + } + if (*ptr == '\"' && *(ptr + 1) == '\0') + return (ft_strdup(arg)); + } + return (ft_strdup(arg)); +} diff --git a/src/parser/loc_env_var_handler_utils.c b/src/parser/loc_env_var_handler_utils.c new file mode 100644 index 00000000..5eef6b29 --- /dev/null +++ b/src/parser/loc_env_var_handler_utils.c @@ -0,0 +1,67 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* loc_env_var_handler_utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: rmikhayl +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/09/10 01:45:18 by rmikhayl #+# #+# */ +/* Updated: 2024/09/10 01:45:21 by rmikhayl ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "tokens.h" + +char *ev_loop(char **start, t_ms_data *data, char *str_start, \ + char *expanded_str) +{ + char *var_name; + char *var_start; + char *expanded_var; + char *tmp; + int len_before_var; + + var_start = *start; + (*start)++; + while (**start && (ft_isalnum(**start) || **start == '_')) + (*start)++; + var_name = ft_substr(var_start, 0, *start - var_start); + expanded_var = expand_env_and_loc_var(var_name, data); + free(var_name); + len_before_var = var_start - str_start; + tmp = ft_substr(str_start, 0, len_before_var); + expanded_str = ft_strjoin_free(expanded_str, tmp); + free(tmp); + expanded_str = ft_strjoin_free(expanded_str, expanded_var); + free(expanded_var); + return (expanded_str); +} + +char *expand_variable(char **start, t_ms_data *data) +{ + char *expanded_str; + char *str_start; + char *result; + + result = NULL; + str_start = *start; + expanded_str = ft_strdup(""); + while (**start && **start != '\0') + { + if (**start == '$') + { + expanded_str = ev_loop(start, data, str_start, expanded_str); + str_start = *start; + str_start = str_start_adj(str_start); + } + else + (*start)++; + } + if (str_start != *start) + { + result = ft_substr(str_start, 0, *start - str_start); + expanded_str = ft_strjoin_free(expanded_str, result); + free(result); + } + return (expanded_str); +} diff --git a/src/parser/loc_env_var_handler_utils_utils.c b/src/parser/loc_env_var_handler_utils_utils.c new file mode 100644 index 00000000..2fae69f9 --- /dev/null +++ b/src/parser/loc_env_var_handler_utils_utils.c @@ -0,0 +1,86 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* loc_env_var_handler_utils_utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: rmikhayl +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/09/10 01:45:18 by rmikhayl #+# #+# */ +/* Updated: 2024/09/10 01:45:21 by rmikhayl ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "tokens.h" + +char *expand_env_and_loc_var(char *arg, t_ms_data *data); +void final_quote_removal(int arg_count, t_ast *command_node); +char *get_env_variable(char *arg, t_ms_data *data); +void handle_trailing_quote(char *arg); +char *get_exit_status(t_ms_data *data); + +void final_quote_removal(int arg_count, t_ast *command_node) +{ + int i; + size_t len; + char *arg; + char *trimmed_arg; + + i = 0; + while (i < arg_count) + { + arg = command_node->args[i]; + len = ft_strlen(arg); + if ((arg[0] == '"' && arg[len - 1] == '"') || (arg[0] == '\'' + && arg[len - 1] == '\'')) + { + trimmed_arg = ft_strndup(arg + 1, len - 2); + free(command_node->args[i]); + command_node->args[i] = trimmed_arg; + } + i++; + } +} + +char *expand_env_and_loc_var(char *arg, t_ms_data *data) +{ + char *env_value_dup; + + arg = exit_status_adj(arg); + if (ft_strcmp(arg, "$?") == 0) + return (get_exit_status(data)); + else if (arg[0] == '$') + { + handle_trailing_quote(arg); + env_value_dup = get_env_variable(arg, data); + return (env_value_dup); + } + return (ft_strdup("")); +} + +char *get_exit_status(t_ms_data *data) +{ + char *exit_status; + char *exit_status_dup; + + exit_status = get_shell_variable(data->shell_variables, "?"); + exit_status_dup = ft_strdup(exit_status); + return (exit_status_dup); +} + +void handle_trailing_quote(char *arg) +{ + if (arg[ft_strlen(arg) - 1] == '"') + arg[ft_strlen(arg) - 1] = '\0'; +} + +char *get_env_variable(char *arg, t_ms_data *data) +{ + char *env_value; + + env_value = get_env(data->envp, arg + 1); + if (!env_value) + env_value = get_env(data->shell_variables, arg + 1); + if (env_value) + return (ft_strdup(env_value)); + return (ft_strdup("")); +} diff --git a/src/parser/loc_env_var_handler_utils_utils_utils.c b/src/parser/loc_env_var_handler_utils_utils_utils.c new file mode 100644 index 00000000..2a74ab8b --- /dev/null +++ b/src/parser/loc_env_var_handler_utils_utils_utils.c @@ -0,0 +1,88 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* loc_env_var_handler_utils_utils_utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: rmikhayl +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/09/10 01:45:50 by rmikhayl #+# #+# */ +/* Updated: 2024/09/10 01:45:52 by rmikhayl ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "tokens.h" + +char *exit_status_adj(char *arg); +int is_in_single_quotes(char *arg); +char *str_start_adj(char *arg); +char *tmp_adj(char *arg); +char *append_literal(char **start, char *processed_arg); + +char *exit_status_adj(char *arg) +{ + if (ft_strcmp(arg, "$") == 0) + return ("$?"); + return (arg); +} + +int is_in_single_quotes(char *arg) +{ + int len; + + if (!arg || arg[0] != '\'') + return (0); + len = 0; + while (arg[len] != '\0') + len++; + if (arg[len - 1] == '\'') + return (1); + return (0); +} + +char *str_start_adj(char *arg) +{ + if (!ft_strcmp(arg, "?") || !ft_strcmp(arg, "?\"")) + return (""); + else if (!ft_strcmp(arg, "?\'")) + return ("\'"); + return (arg); +} + +char *tmp_adj(char *arg) +{ + char *ptr; + char *tmp_adj_dup; + + if (*arg == '\"') + { + ptr = arg + 1; + while (*ptr) + { + if (!ft_isdigit(*ptr)) + return (arg); + ptr++; + } + tmp_adj_dup = ft_strdup(arg + 1); + free(arg); + return (tmp_adj_dup); + } + tmp_adj_dup = ft_strdup(arg); + free(arg); + return (tmp_adj_dup); +} + +char *append_literal(char **start, char *processed_arg) +{ + char *literal_part; + char *literal_start; + char *tmp; + + literal_start = *start; + while (**start != '\0' && **start != '$') + (*start)++; + literal_part = ft_substr(literal_start, 0, *start - literal_start); + tmp = ft_strjoin(processed_arg, literal_part); + free(literal_part); + free(processed_arg); + return (tmp); +} diff --git a/src/parser/parser_helper_helpers.c b/src/parser/parser_helper_helpers.c deleted file mode 100644 index e9ae7d9c..00000000 --- a/src/parser/parser_helper_helpers.c +++ /dev/null @@ -1,96 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* parser_helper_helpers.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: rocky +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2024/08/28 20:36:33 by rocky #+# #+# */ -/* Updated: 2024/08/28 20:36:39 by rocky ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#include "tokens.h" -#include "execute.h" - -void final_quote_removal(int arg_count, t_ast *command_node) -{ - int i; - size_t len; - char *arg; - char *trimmed_arg; - - i = 0; - while (i < arg_count) - { - arg = command_node->args[i]; - len = ft_strlen(arg); - if ((arg[0] == '"' && arg[len - 1] == '"') || (arg[0] == '\'' \ - && arg[len - 1] == '\'')) - { - trimmed_arg = ft_strndup(arg + 1, len - 2); - free(command_node->args[i]); - command_node->args[i] = trimmed_arg; - } - i++; - } -} - -char *expand_env_and_loc_var(char *arg, t_ms_data *data) -{ - char *env_value; - - if (ft_strcmp(arg, "$?") == 0) - return (ft_itoa(data->exit_status)); - else if (arg[0] == '$') - { - if (arg[ft_strlen(arg) - 1] == '"') - arg[ft_strlen(arg) - 1] = '\0'; - env_value = get_env(data->envp, arg + 1); - if (!env_value) - env_value = get_env(data->shell_variables, arg + 1); - if (env_value) - return (ft_strdup(env_value)); - } - return (ft_strdup("")); -} - -void handle_local_vars(t_ms_data *data, char *arg) -{ - char *p; - int valid_var; - - p = arg; - valid_var = 1; - if (arg[0] != '=' && strchr(arg, '=')) - { - while (p < strchr(arg, '=')) - { - if (!ft_isalnum(*p++)) - { - valid_var = 0; - break ; - } - } - if (valid_var) - handle_add_set_shell_variable(&data->shell_variables, arg); - } -} - -void post_process_command_args(t_ast *command_node, int arg_count \ - , t_ms_data *data) -{ - int i; - char *processed_arg; - - i = 0; - while (i < arg_count) - { - handle_local_vars(data, command_node->args[i]); - processed_arg = process_argument(command_node->args[i], data); - free(command_node->args[i]); - command_node->args[i] = processed_arg; - i++; - } - final_quote_removal(arg_count, command_node); -} diff --git a/src/parser/parser_helpers.c b/src/parser/parser_helpers.c deleted file mode 100644 index 525f6f76..00000000 --- a/src/parser/parser_helpers.c +++ /dev/null @@ -1,93 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* parser_helpers.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: rocky +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2024/08/28 20:13:42 by rocky #+# #+# */ -/* Updated: 2024/08/28 20:14:33 by rocky ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#include "tokens.h" - -t_ast *new_ast_node(t_token_type type); -t_ast *create_redir(t_token **tokens, t_token *tmp, t_ms_data *data); -int arg_len(t_token *current); -void set_command_args(t_ast *command_node, t_token **tokens, int arg_count); -t_ast *manage_commands(t_token **tokens, t_ms_data *data); - -t_ast *new_ast_node(t_token_type type) -{ - t_ast *node; - - node = malloc(sizeof(t_ast)); - if (!node) - return (NULL); - node->type = type; - node->args = NULL; - node->left = NULL; - node->right = NULL; - return (node); -} - -t_ast *create_redir(t_token **tokens, t_token *tmp, t_ms_data *data) -{ - t_ast *redirect_node; - - redirect_node = new_ast_node((*tokens)->type); - *tokens = (*tokens)->next->next; - redirect_node->left = manage_redirs(tokens, data); - redirect_node->right = create_redir_node(tmp->next); - free(tmp->data); - free(tmp); - return (redirect_node); -} - -int arg_len(t_token *current) -{ - int arg_count; - - arg_count = 0; - while (current && current->type == PHRASE) - { - arg_count++; - current = current->next; - } - return (arg_count); -} - -void set_command_args(t_ast *command_node, t_token **tokens, \ - int arg_count) -{ - int i; - t_token *tmp; - - i = 0; - while (i < arg_count) - { - command_node->args[i] = ft_strdup((*tokens)->data); - tmp = *tokens; - *tokens = (*tokens)->next; - free(tmp->data); - free(tmp); - i++; - } - command_node->args[arg_count] = NULL; -} - -t_ast *manage_commands(t_token **tokens, t_ms_data *data) -{ - t_ast *command_node; - int arg_count; - - command_node = new_ast_node(PHRASE); - arg_count = arg_len(*tokens); - command_node->args = malloc(sizeof(char *) * (arg_count + 1)); - if (!command_node->args) - return (NULL); - set_command_args(command_node, tokens, arg_count); - post_process_command_args(command_node, arg_count, data); - return (command_node); -} diff --git a/src/parser/parser_joint_vars.c b/src/parser/parser_joint_vars.c deleted file mode 100644 index 94bbd0b4..00000000 --- a/src/parser/parser_joint_vars.c +++ /dev/null @@ -1,73 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* parser_joint_vars.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: rmikhayl +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2024/09/04 16:46:53 by rmikhayl #+# #+# */ -/* Updated: 2024/09/04 16:46:57 by rmikhayl ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#include - -char *expand_variable(char **start, t_ms_data *data) -{ - char *var_name; - char *expanded_var; - char *var_start; - - var_start = *start; - (*start)++; - while (**start != '\0' && (ft_isalnum(**start) || **start == '_')) - (*start)++; - var_name = ft_substr(var_start, 0, *start - var_start); - expanded_var = expand_env_and_loc_var(var_name, data); - free(var_name); - return (expanded_var); -} - -char *append_literal(char **start, char *processed_arg) -{ - char *literal_part; - char *literal_start; - char *tmp; - - literal_start = *start; - while (**start != '\0' && **start != '$') - (*start)++; - literal_part = ft_substr(literal_start, 0, *start - literal_start); - tmp = ft_strjoin(processed_arg, literal_part); - free(literal_part); - free(processed_arg); - return (tmp); -} - -char *process_argument(char *arg, t_ms_data *data) -{ - char *start; - char *processed_arg; - char *tmp; - char *expanded_var; - - processed_arg = ft_strdup(""); - start = arg; - while (*start != '\0') - { - if (*start == '$') - { - expanded_var = expand_variable(&start, data); - if (expanded_var != NULL) - { - tmp = ft_strjoin(processed_arg, expanded_var); - free(processed_arg); - processed_arg = tmp; - free(expanded_var); - } - } - else - processed_arg = append_literal(&start, processed_arg); - } - return (processed_arg); -} diff --git a/src/redirection/redirect_heredoc.c b/src/redirection/redirect_heredoc.c index 1edd6c5c..b6c51352 100644 --- a/src/redirection/redirect_heredoc.c +++ b/src/redirection/redirect_heredoc.c @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* redirect_heredoc.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: dmdemirk +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2024/07/11 14:32:29 by dmdemirk #+# #+# */ -/* Updated: 2024/07/11 16:00:30 by dmdemirk ### ########.fr */ +/* Created: 2024/09/06 13:46:24 by rocky #+# #+# */ +/* Updated: 2024/09/09 13:50:24 by dmdemirk ### ########.fr */ /* */ /* ************************************************************************** */ @@ -16,105 +16,44 @@ #include "execute.h" #include #include +#include "signals.h" -int redirect_here_doc(t_ast *node, t_ms_data *data); -static int open_tmp_file(const char *type); -static void execute_child(t_ast *node, t_ms_data *data, int *file_fd); - -/** - - @brief This function handle "<<" heredoc functionality - - - - @param node current node in the AST - - @param data minishell data structure - - @return status: - - 0: success - - 1: error +/* + GLOBAL VAR + volatile tells compiler the var can change at compilation between accesses. + sig_atomic_t used for global_vars */ -static char *assemble_result(char **tokens, size_t result_len) -{ - char *result; - int i; +volatile sig_atomic_t g_heredoc_interrupted = 0; - result = malloc(result_len + 1); - if (!result) - return (NULL); - *result = '\0'; - i = 0; - while (tokens[i]) - { - ft_strcat(result, tokens[i]); - if (tokens[i + 1]) - ft_strcat(result, " "); - i++; - } - free(tokens); - return (result); -} +static void setup_sigint_handler(struct sigaction *sa_old); +static int handle_heredoc_interruption(char *line, char *eof, int file_fd, \ + struct sigaction *sa_old); +static void execute_child(t_ast *node, t_ms_data *data, int *file_fd); +static void write_heredoc_lines(char **line, int file_fd, char *eof, \ + t_ms_data *data); +int redirect_here_doc(t_ast *node, t_ms_data *data); -char *process_and_reassemble(char *line, t_ms_data *data) +static void setup_sigint_handler(struct sigaction *sa_old) { - char **tokens; - size_t result_len; - int i; - char *processed_token; + struct sigaction sa_new; - tokens = ft_split(line, ' '); - if (!tokens) - return (NULL); - result_len = 0; - i = 0; - while (tokens[i]) - { - processed_token = expand_env_and_loc_var(tokens[i], data); - free(tokens[i]); - tokens[i] = processed_token; - result_len += ft_strlen(tokens[i]) + 1; - i++; - } - return (assemble_result(tokens, result_len)); + sa_new.sa_handler = handle_sigint_heredoc; + sigemptyset(&sa_new.sa_mask); + sa_new.sa_flags = 0; + sigaction(SIGINT, &sa_new, sa_old); } -int redirect_here_doc(t_ast *node, t_ms_data *data) +static int handle_heredoc_interruption(char *line, char *eof, int file_fd, \ + struct sigaction *sa_old) { - char *line; - char *eof; - int file_fd; - - line = NULL; - if (node->right->args[0] == NULL) - return (1); - file_fd = open_tmp_file("w"); - eof = ft_strdup(node->right->args[0]); - line = process_and_reassemble(readline("> "), data); - while (line && (ft_strcmp(line, eof) != 0)) - { - write(file_fd, line, ft_strlen(line)); - write(file_fd, "\n", 1); - free(line); - line = process_and_reassemble(readline("> "), data); - } free(line); free(eof); close(file_fd); - file_fd = open_tmp_file("r"); - execute_child(node->left, data, &file_fd); unlink("/tmp/heredoc"); - return (0); -} - -static int open_tmp_file(const char *type) -{ - int file_fd; - - file_fd = -1; - if (ft_strcmp(type, "w") == 0) - file_fd = open("/tmp/heredoc", O_WRONLY | O_CREAT | O_TRUNC, 0644); - else if (ft_strcmp(type, "r") == 0) - file_fd = open("/tmp/heredoc", O_RDONLY); - if (file_fd < 0) - ft_perror("open"); - return (file_fd); + g_heredoc_interrupted = 0; + sigaction(SIGINT, sa_old, NULL); + return (1); } static void execute_child(t_ast *node, t_ms_data *data, int *file_fd) @@ -133,3 +72,43 @@ static void execute_child(t_ast *node, t_ms_data *data, int *file_fd) close(*file_fd); waitpid(pid, &data->exit_status, 0); } + +void write_heredoc_lines(char **line, int file_fd, char *eof, \ + t_ms_data *data) +{ + while (*line && (ft_strcmp(*line, eof) != 0) && !g_heredoc_interrupted) + { + write(file_fd, *line, ft_strlen(*line)); + write(file_fd, "\n", 1); + free(*line); + (void)data; + *line = readline("🌞 > "); + } +} + +int redirect_here_doc(t_ast *node, t_ms_data *data) +{ + char *line; + char *eof; + int file_fd; + struct sigaction sa_old; + + line = NULL; + if (node->right->args[0] == NULL) + return (1); + setup_sigint_handler(&sa_old); + file_fd = open_tmp_file("w"); + eof = ft_strdup(node->right->args[0]); + line = process_and_reassemble(readline("🌞 > "), data); + write_heredoc_lines(&line, file_fd, eof, data); + if (g_heredoc_interrupted) + return (handle_heredoc_interruption(line, eof, file_fd, &sa_old)); + free(line); + free(eof); + close(file_fd); + sigaction(SIGINT, &sa_old, NULL); + file_fd = open_tmp_file("r"); + execute_child(node->left, data, &file_fd); + unlink("/tmp/heredoc"); + return (0); +} diff --git a/src/redirection/redirect_out.c b/src/redirection/redirect_out.c index a2275d67..4753ca22 100644 --- a/src/redirection/redirect_out.c +++ b/src/redirection/redirect_out.c @@ -6,7 +6,7 @@ /* By: dmdemirk -int redirect_out(t_ast *node, t_ms_data *data); +static int open_and_redirect(t_ast *node, t_ms_data *data); +int redirect_out(t_ast *node, t_ms_data *data); /** - @brief redirect out ">" to the file output @@ -29,6 +30,61 @@ int redirect_out(t_ast *node, t_ms_data *data); - 1: error */ +/* + int redirect_out(t_ast *node, t_ms_data *data) + { + pid_t pid; + int status; + int fd; + + pid = fork(); + if (pid == -1) + return (1); + if (pid == 0) + { + if (data->std_out == -1) + { + data->std_out = open_file(node->right, ">"); + if (data->std_out == -1) + return (1); + } + else + { + fd = open_file(node->right, ">"); + if (fd == -1) + return (1); + dup2(fd, STDOUT_FILENO); + close(fd); + } + execute_ast(node->left, data); + exit(0); + } + waitpid(pid, &status, 0); + return (WEXITSTATUS(status)); + } + */ + +static int open_and_redirect(t_ast *node, t_ms_data *data) +{ + int fd; + + if (data->std_out == -1) + { + data->std_out = open_file(node->right, ">"); + if (data->std_out == -1) + return (1); + } + else + { + fd = open_file(node->right, ">"); + if (fd == -1) + return (1); + dup2(fd, STDOUT_FILENO); + close(fd); + } + return (0); +} + int redirect_out(t_ast *node, t_ms_data *data) { pid_t pid; @@ -39,9 +95,8 @@ int redirect_out(t_ast *node, t_ms_data *data) return (1); if (pid == 0) { - data->std_out = open_file(node->right, ">"); - if (data->std_out == -1) - return (1); + if (open_and_redirect(node, data) != 0) + exit(1); execute_ast(node->left, data); exit(0); } diff --git a/src/redirection/utils.c b/src/redirection/utils.c index 30501db2..3b838988 100644 --- a/src/redirection/utils.c +++ b/src/redirection/utils.c @@ -6,7 +6,7 @@ /* By: dmdemirk #include "libft.h" #include "tokens.h" +#include "exit_status.h" int open_file(t_ast *node, char *direction); +int open_tmp_file(const char *type); /** - @brief open file in the context of redirection @@ -38,7 +40,7 @@ int open_file(t_ast *node, char *direction) else if (ft_strcmp(direction, ">") == 0) fd = open(node->args[0], O_WRONLY | O_CREAT | O_TRUNC, 0644); else if ((ft_strcmp(direction, ">>") == 0) \ - || (ft_strcmp(direction, "temp") == 0)) + || (ft_strcmp(direction, "temp") == 0)) fd = open(node->args[0], O_WRONLY | O_CREAT | O_APPEND, 0644); else if (ft_strcmp(direction, "tty") == 0) fd = open("/dev/tty", O_RDWR); @@ -46,3 +48,17 @@ int open_file(t_ast *node, char *direction) fd = -1; return (fd); } + +int open_tmp_file(const char *type) +{ + int file_fd; + + file_fd = -1; + if (ft_strcmp(type, "w") == 0) + file_fd = open("/tmp/heredoc", O_WRONLY | O_CREAT | O_TRUNC, 0644); + else if (ft_strcmp(type, "r") == 0) + file_fd = open("/tmp/heredoc", O_RDONLY); + if (file_fd < 0) + ft_perror("open"); + return (file_fd); +} diff --git a/src/shell_variables/shell_variables.c b/src/shell_variables/shell_variables.c index 03f9101c..d3cfac72 100644 --- a/src/shell_variables/shell_variables.c +++ b/src/shell_variables/shell_variables.c @@ -6,7 +6,7 @@ /* By: dmdemirk std_out); ft_putstr_fd("\n", data->std_out); + free(value); return (0); } return (-1); @@ -66,6 +66,10 @@ int handle_shell_variable(t_ast *node, t_ms_data *data) void shell_variable_update(t_ms_data *data, int status) { + char *status_str; + data->exit_status = status; - set_shell_var(&data->shell_variables, "?", ft_itoa(status)); + status_str = ft_itoa(status); + set_shell_var(&data->shell_variables, "?", status_str); + free(status_str); } diff --git a/src/shell_variables/shell_variables_utils.c b/src/shell_variables/shell_variables_utils.c index b4c53fe9..fd0a8488 100644 --- a/src/shell_variables/shell_variables_utils.c +++ b/src/shell_variables/shell_variables_utils.c @@ -6,7 +6,7 @@ /* By: dmdemirk key = ft_strdup(key); - new_node->value = ft_strdup(value); free(key); + new_node->value = ft_strdup(value); new_node->next = NULL; if (*shell_var == NULL) - { *shell_var = new_node; - return ; + else + { + curr_node = *shell_var; + while (curr_node->next != NULL) + curr_node = curr_node->next; + curr_node->next = new_node; } - curr_node = *shell_var; - while (curr_node->next != NULL) - curr_node = curr_node->next; - curr_node->next = new_node; } void set_shell_var(t_env **shell_var, const char *key, const char *value) @@ -85,3 +86,19 @@ char *get_shell_variable(t_env *shell_var, const char *key) } return (NULL); } + +void free_shell_var_list(t_env *shell_var) +{ + t_env *curr_node; + t_env *next_node; + + curr_node = shell_var; + while (curr_node) + { + next_node = curr_node->next; + free(curr_node->key); + free(curr_node->value); + free(curr_node); + curr_node = next_node; + } +} diff --git a/src/signals/signals.c b/src/signals/signals.c index 4fbdfc4f..9a02524f 100644 --- a/src/signals/signals.c +++ b/src/signals/signals.c @@ -6,7 +6,7 @@ /* By: dmdemirk +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/09/06 13:43:47 by rocky #+# #+# */ +/* Updated: 2024/09/06 13:43:49 by rocky ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "signals.h" +#include +#include +#include +#include "libft.h" + +void handle_sigint_heredoc(int signo) +{ + (void)signo; + g_heredoc_interrupted = 1; + write(1, "\n", 1); + rl_replace_line("", 0); + rl_redisplay(); +} diff --git a/src/test/cases.txt b/src/test/cases.txt new file mode 100644 index 00000000..fd8ea531 --- /dev/null +++ b/src/test/cases.txt @@ -0,0 +1,55 @@ +illegal input: +hello" +a < < b +cat Makefile > +| file.c + +loc_vars: +a=cho b=456 +e$a $b +e$a$b +echo a$ab$bb + +operators: +ls -la > output.txt +sort < output.txt +echo "New entry" >> output.txt +ls -la > output.txt > new.txt +cat << a | cat << b | cat << c +ls -la | grep ".txt" +cat < output.txt | sort > sorted_output.txt + +heredoc: +cat << eof +This is line 1 +This is line 2 +This is line 3 +eof + +cat << eof +> $USER '$USER' "$USER" USER $? "$?" '$?' +> eof +rmikhayl +echo & quote mark management +echo '$USER' prints $USER + +exit status +echo $? +echo $? + '$' + +env_vars: +echo $USER '$USER' "$USER" USER $? "$?" '$?' +export MY_VAR="Hello, World!" +env (see it there) +export MY_VAR="new value" (creates another copy, should overwrite) +unset MY_VAR + +difficult input: +ls -la | +cat out.txt | grep Makefile | wc -l + +signals: +grep"rubbish" exit with ctrl+C +ctrl+D +heredoc exit with ctrl+D with warning +ctrl+\ \ No newline at end of file diff --git a/src/utils/clean_general.c b/src/utils/clean_general.c index 59347dda..9d6ce047 100644 --- a/src/utils/clean_general.c +++ b/src/utils/clean_general.c @@ -6,12 +6,20 @@ /* By: rocky +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/06/11 14:56:25 by rocky #+# #+# */ -/* Updated: 2024/07/17 14:45:30 by dmdemirk ### ########.fr */ +/* Updated: 2024/09/09 15:41:16 by dmdemirk ### ########.fr */ /* */ /* ************************************************************************** */ #include "tokens.h" #include "env.h" +#include "exit_status.h" + +void free_args(char **args); +void free_env_list(t_env *env); +void free_ms_data(t_ms_data *data); +void loop_cleanup(t_loop_data *loop_data, t_token *tokens_head); +void free_ast(t_ast *node); +void free_all_tokens(t_token *tokens); void free_args(char **args) { @@ -32,10 +40,10 @@ void free_env_list(t_env *env) while (env) { - free(env->key); - free(env->value); temp = env; env = env->next; + free(env->key); + free(env->value); free(temp); } } @@ -44,22 +52,43 @@ void free_ms_data(t_ms_data *data) { if (data) { - free_env_list(data->envp); - free_env_list(data->shell_variables); + free_shell_var_list(data->envp); + free_shell_var_list(data->shell_variables); free(data->current_dir); - if (data->std_in != STDIN_FILENO) + if (data->std_in >= 0) close(data->std_in); - if (data->std_out != STDOUT_FILENO) + if (data->std_out >= 0) close(data->std_out); - if (data->std_err != STDERR_FILENO) + if (data->std_err >= 0) close(data->std_err); } } -void loop_cleanup(char *line, t_token *tokens, char *prompt, t_ast *tree) +void loop_cleanup(t_loop_data *loop_data, t_token *tokens_head) +{ + free(loop_data->trimmed_input); + free_all_tokens(tokens_head); + free(loop_data->prompt); + free_ast(loop_data->tree); +} + +void free_ast(t_ast *node) { - free(line); - free(prompt); - (void)tokens; - free_ast(tree); + int i; + + i = 0; + if (!node) + return ; + if (node->args) + { + while (node->args && node->args[i]) + { + free(node->args[i]); + i++; + } + free(node->args); + } + free_ast(node->left); + free_ast(node->right); + free(node); } diff --git a/src/utils/clean_tree.c b/src/utils/clean_utils.c similarity index 61% rename from src/utils/clean_tree.c rename to src/utils/clean_utils.c index 9d616d36..48ef8cc6 100644 --- a/src/utils/clean_tree.c +++ b/src/utils/clean_utils.c @@ -1,18 +1,19 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* clean_tree.c :+: :+: :+: */ +/* clean_utils.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: rocky +#+ +:+ +#+ */ +/* By: dmdemirk type == PHRASE && node->args) - { - while (node->args && node->args[i]) - { - free(node->args[i]); - i++; - } - free(node->args); - } - free_ast(node->left); - free_ast(node->right); - free(node); -} diff --git a/src/utils/initialise.c b/src/utils/initialise.c index dfb6e0b3..9f449d0d 100644 --- a/src/utils/initialise.c +++ b/src/utils/initialise.c @@ -25,6 +25,7 @@ void init_ms_data(t_ms_data *data, char **argv, char **envp) init_env(&data->envp, envp); data->shell_variables = NULL; handle_add_set_shell_variable(&data->shell_variables, "_=/usr/bin/env"); + set_shell_var(&data->shell_variables, "?", "0"); data->current_dir = getcwd(NULL, 0); data->exit_status = 0; data->std_in = -1; diff --git a/src/utils/prompt.c b/src/utils/prompt.c index b04b6daf..c959a286 100644 --- a/src/utils/prompt.c +++ b/src/utils/prompt.c @@ -24,7 +24,7 @@ char *generate_prompt(t_ms_data *data) prompt_len = ft_strlen("🌴 @maxishell$ ") + \ ft_strlen(getenv("LOGNAME")); - prompt = (char *)malloc(prompt_len); + prompt = (char *)malloc(prompt_len + 1); if (!prompt) exit(EXIT_FAILURE); ft_strcpy(prompt, "🌴 ");