commit 814bac23a73665bd187c83f2333eb855c49a8a41 Author: Victor Vobis Date: Wed Jun 4 14:58:04 2025 +0200 first commit diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..deb0502 --- /dev/null +++ b/Makefile @@ -0,0 +1,112 @@ +# **************************************************************************** # +# # +# ::: :::::::: # +# Makefile :+: :+: :+: # +# +:+ +:+ +:+ # +# By: anarama +#+ +:+ +#+ # +# +#+#+#+#+#+ +#+ # +# Created: 2024/07/05 12:24:47 by victor #+# #+# # +# Updated: 2025/06/02 18:50:03 by victor ### ########.fr # +# # +# **************************************************************************** # + +# COMPILER AND FLAGS +CC := cc +CFLAGS := -Werror -Wall -Wextra + +# DIRECTORIES +SRCDIR := src +ASTDIR := ast +BULDINDIR := builtin +OBJDIR := obj +TOKENDIR := tokenizer +BINDIR := bin + +SRC := src/commands.c src/environment_variables.c \ + src/handle_signals.c src/input.c src/list_memory.c \ + src/list.c src/minishell.c \ + src/path_utils.c src/termios.c \ + src/utils.c src/utils2.c src/utils3.c \ + src/environment_variables_manip.c \ + src/wildcards.c src/execution.c \ + src/non_interactive.c src/wildcards_hanlde_match.c \ + src/wildcards_helper.c + +PROMPT_SRC := prompt/prompt_input.c prompt/prompt_string_management.c \ + prompt/prompt_utils.c prompt/tab_completion.c \ + prompt/escape_sequences.c prompt/arrowkeys.c \ + prompt/prompt_print.c prompt/tab_get_word.c \ + prompt/non_blocking_mode.c prompt/prompt_handle_chars.c \ + +AST_SRC := ast/ast_utils.c \ + ast/handle_command.c ast/handle_fds.c \ + ast/parse_tokens.c ast/parser.c \ + ast/syntax_check.c ast/handle_redirs.c \ + ast/handle_heredoc.c ast/parse_tokens_helper.c \ + ast/syntax_check_helper.c ast/buildin.c + +TOKEN_SRC := tokenizer/check_special_symbol.c \ + tokenizer/create_token_double_special_symbol.c \ + tokenizer/create_token_single_special_symbol.c \ + tokenizer/create_token_word.c \ + tokenizer/create_token.c \ + tokenizer/tokenizer.c \ + tokenizer/subshell.c tokenizer/evaluate_input.c \ + tokenizer/input_skip_patterns.c \ + tokenizer/token_heredoc.c \ + tokenizer/tokenizer_heredoc_helper.c tokenizer/evaluate_input_helper.c \ + tokenizer/evaluate_input_helper2.c + +BUILDIN_SRC := builtin/ft_echo.c builtin/ft_env.c \ + builtin/ft_pwd.c builtin/ft_unset.c \ + builtin/ft_export.c builtin/ft_exit.c \ + builtin/ft_cd.c + +# OBJECT FILES +OBJ := $(SRC:%.c=$(OBJDIR)/%.o) +AST_OBJ := $(AST_SRC:ast/%.c=$(OBJDIR)/ast/%.o) +BUILDIN_OBJ := $(BUILDIN_SRC:builtin/%.c=$(OBJDIR)/builtin/%.o) +PROMPT_OBJ := $(PROMPT_SRC:prompt/%.c=$(OBJDIR)/prompt/%.o) +TOKEN_OBJ := $(TOKEN_SRC:tokenizer/%.c=$(OBJDIR)/tokenizer/%.o) + +NAME := $(BINDIR)/minishell +LIBS := libft/libft.a + +# Create object directory if none exists +$(shell mkdir -p $(BINDIR) $(OBJDIR) $(OBJDIR)/ast $(OBJDIR)/src $(OBJDIR)/tokenizer $(OBJDIR)/builtin $(OBJDIR)/prompt) + +all: $(NAME) + +$(NAME): $(OBJ) $(AST_OBJ) $(TOKEN_OBJ) $(BUILDIN_OBJ) $(PROMPT_OBJ) $(LIBS) minishell.h + $(CC) -static $(CFLAGS) $(OBJ) $(AST_OBJ) $(TOKEN_OBJ) $(BUILDIN_OBJ) $(PROMPT_OBJ) $(LIBS) -o $(NAME) + +test: $(TEST_OBJ) $(AST_OBJ) $(TOKEN_OBJ) $(LIBS) minishell.h + $(CC) $(CFLAGS) $(TEST_OBJ) $(AST_OBJ) $(TOKEN_OBJ) $(LIBS) -o $(TEST_NAME) + +clean: + make clean -C libft + rm -rf $(OBJ) $(AST_OBJ) $(TEST_OBJ) $(TOKEN_OBJ) $(PROMPT_OBJ) $(BUILDIN_OBJ) + +fclean: clean + rm -f $(NAME) $(TEST_NAME) + make fclean -C libft + +re: fclean all + +$(OBJDIR)/%.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ + +$(OBJDIR)/builtin/%.o: builtin/%.c + $(CC) $(CFLAGS) -c $< -o $@ + +$(OBJDIR)/prompt/%.o: prompt/%.c + $(CC) $(CFLAGS) -c $< -o $@ + +$(OBJDIR)/ast/%.o: ast/%.c + $(CC) $(CFLAGS) -c $< -o $@ + +$(OBJDIR)/tokenizer/%.o: tokenizer/%.c + $(CC) $(CFLAGS) -c $< -o $@ + +$(LIBS): + make bonus -C libft diff --git a/ast/ast_utils.c b/ast/ast_utils.c new file mode 100644 index 0000000..c33c1c3 --- /dev/null +++ b/ast/ast_utils.c @@ -0,0 +1,62 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ast_utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: anarama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/07/20 17:43:20 by anarama #+# #+# */ +/* Updated: 2024/08/16 11:36:37 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +int get_tokens_len(t_token *tokens) +{ + int i; + + i = 0; + while (tokens[i].token_type != TOKEN_EOL) + { + i++; + } + return (i); +} + +char **copy_args(t_ast *node, char **src) +{ + char **temp; + + node->args = ft_calloc(get_split_size((const char **)src) \ + + 1, sizeof(char *)); + if (!node->args) + { + free(node); + perror("calloc in copy args"); + lst_memory(NULL, NULL, CLEAN); + } + lst_memory(node->args, free_split, ADD); + temp = node->args; + while (*src) + { + *node->args = ft_strdup(*src); + if (!*node->args) + { + free(node); + perror("strdup in copy args"); + lst_memory(NULL, NULL, CLEAN); + } + src++; + node->args++; + } + return (temp); +} + +int is_redirection(t_token_type token_type) +{ + return (token_type == TOKEN_REDIRECT_IN + || token_type == TOKEN_REDIRECT_OUT + || token_type == TOKEN_REDIRECT_APPEND + || token_type == TOKEN_HEREDOC); +} diff --git a/ast/buildin.c b/ast/buildin.c new file mode 100644 index 0000000..3d4416e --- /dev/null +++ b/ast/buildin.c @@ -0,0 +1,28 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* buildin.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/26 12:39:13 by vvobis #+# #+# */ +/* Updated: 2024/08/26 12:39:22 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +bool is_buildin(t_ast *node) +{ + if (!node->args || !*node->args) + return (false); + if (ft_memcmp(node->args[0], "echo", ft_strlen("echo") + 1) == 0 + || ft_memcmp(node->args[0], "env", ft_strlen("env") + 1) == 0 + || ft_memcmp(node->args[0], "cd", ft_strlen("cd") + 1) == 0 + || ft_memcmp(node->args[0], "pwd", ft_strlen("pwd") + 1) == 0 + || ft_memcmp(node->args[0], "unset", ft_strlen("unset") + 1) == 0 + || ft_memcmp(node->args[0], "export", ft_strlen("export") + 1) == 0 + || ft_memcmp(node->args[0], "exit", ft_strlen("exit") + 1) == 0) + return (true); + return (false); +} diff --git a/ast/handle_command.c b/ast/handle_command.c new file mode 100644 index 0000000..f409378 --- /dev/null +++ b/ast/handle_command.c @@ -0,0 +1,126 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* handle_command.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: anarama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/07/25 18:14:10 by anarama #+# #+# */ +/* Updated: 2024/08/27 15:22:42 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +bool buildin_apply_pipe(t_ast *node, int32_t *exit_status) +{ + if (node->type == NODE_PIPE) + { + ft_dup2(node->pipefd[1], STDOUT_FILENO, "dup2 in buildin_execute"); + ft_close(node->pipefd[1], "close in buildin_execute"); + } + if (node->has_redir_in || node->has_redir_out) + { + return (handle_fds_child_proccess(node, exit_status)); + } + return (true); +} + +void execute_parent(t_ast *command, int32_t *exit_status, pid_t pid) +{ + command->cpid = pid; + if (command->type == NODE_PIPE) + handle_pipe_in_parent(command); + if (command->has_redir_in || command->has_redir_out) + handle_fds_parent_proccess(command, exit_status); +} + +void execute_command( t_ast *command, \ + int32_t *exit_status, \ + int std[2], \ + char *path) +{ + pid_t pid; + char **env; + bool should_execute; + + should_execute = true; + ft_fork(&pid, "execute command"); + if (pid == 0) + { + env = env_static(NULL); + if (command->type == NODE_PIPE) + handle_pipe_in_child(command); + if (command->has_redir_in || command->has_redir_out) + should_execute = handle_fds_child_proccess(command, exit_status); + if (is_buildin(command) && should_execute) + buildin_execute(command, (const char **)env, exit_status); + else if (path && should_execute) + { + execve(path, command->args, (char **)env); + perror("execve"); + } + return (lst_memory(NULL, NULL, END), \ + close_fds(std), exit(*exit_status)); + } + else + execute_parent(command, exit_status, pid); +} + +bool buildin_execute( t_ast *node, \ + const char **environment, \ + int *e) +{ + if (!node->args || !*node->args) + return (false); + if (ft_memcmp(node->args[0], "echo", ft_strlen(node->args[0]) + 1) == 0) + return (ft_echo(node->args, e), 1); + else if (ft_memcmp(node->args[0], "env", ft_strlen(node->args[0]) + 1) == 0) + return (ft_env(environment, e), 1); + else if (ft_memcmp(node->args[0], "cd", ft_strlen(node->args[0]) + 1) == 0) + return (ft_cd(environment, \ + (const char **)node->args, e), 1); + else if (ft_memcmp(node->args[0], "pwd", ft_strlen(node->args[0]) + 1) == 0) + return (ft_pwd(environment, e), 1); + else if (ft_memcmp(node->args[0], "unset", \ + ft_strlen(node->args[0]) + 1) == 0) + return (ft_unset((char **)environment, \ + (const char **)node->args, e), 1); + else if (ft_memcmp(node->args[0], "export", \ + ft_strlen(node->args[0]) + 1) == 0) + ft_export((const char **)node->args, e); + else if (ft_memcmp(node->args[0], "exit", \ + ft_strlen(node->args[0]) + 1) == 0) + return (ft_exit(node, e), *e = 1); + return (0); +} + +void handle_command( t_ast *current, \ + const char **env, \ + int *exit_status, \ + int std[2]) +{ + char *path; + + if (current->type == NODE_PIPE) + ft_pipe(current->pipefd, "in handle_command"); + check_and_expand_wildcards(¤t->args); + if (is_buildin(current) && current->type != NODE_PIPE \ + && current->was_pipe == false) + { + if (buildin_apply_pipe(current, exit_status)) + buildin_execute(current, env, exit_status); + } + else + { + path = NULL; + if (current->args && current->args[0] && current->args[0][0]) + { + if (!is_buildin(current)) + path = find_absolute_path(\ + environment_variable_value_get("PATH", \ + env), current->args[0], exit_status); + } + execute_command(current, exit_status, std, path); + } +} diff --git a/ast/handle_fds.c b/ast/handle_fds.c new file mode 100644 index 0000000..91cff4d --- /dev/null +++ b/ast/handle_fds.c @@ -0,0 +1,83 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* handle_fds.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: andrejarama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/07/25 18:17:10 by anarama #+# #+# */ +/* Updated: 2024/08/27 14:14:23 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +bool fd_out(t_ast *command, int *exit_status) +{ + if (command->has_redir_out && command->path_file_out) + { + if (command->fd_out > 0) + { + ft_dup2(command->fd_out, STDOUT_FILENO, "in hanlde_fds_child"); + } + else + return (*exit_status = 1, false); + } + return (*exit_status = 0, true); +} + +bool handle_fds_child_proccess(t_ast *command, int32_t *exit_status) +{ + if (command->has_redir_in && command->path_file_in != 0) + { + if (access(command->path_file_in, F_OK) == 0) + { + ft_open(&command->fd_in, command->path_file_in, O_RDONLY, 0644); + if (command->is_heredoc == true) + { + command->is_heredoc = false; + if (unlink(command->path_file_in)) + perror("unlink"); + ft_free(&command->path_file_in); + } + ft_dup2(command->fd_in, STDIN_FILENO, "in hanlde_fds_child"); + } + else + return (p_stderr(2, "minishell: %s: No such file or directory\n", \ + command->path_file_in), command->type = NODE_INVALID, \ + *exit_status = 1, false); + } + if (command->has_redir_out && command->path_file_out) + return (fd_out(command, exit_status)); + return (*exit_status = 0, true); +} + +void handle_fds_parent_proccess(t_ast *command, int32_t *exit_status) +{ + if (command->has_redir_in) + { + if (command->fd_in == -1 && command->path_file_in == 0) + *exit_status = 1; + if (command->is_heredoc == true && command->path_file_in) + ft_free(&command->path_file_in); + } + if (command->has_redir_out && command->path_file_out && command->fd_out > 0) + { + ft_close(command->fd_out, "in hanlde_fds_parents"); + command->fd_out = -1; + } +} + +void handle_pipe_in_child(t_ast *command) +{ + ft_dup2(command->pipefd[1], STDOUT_FILENO, "dup2 in pipe_child"); + ft_close(command->pipefd[0], "close in pipe_child"); + ft_close(command->pipefd[1], "close in pipe_child"); +} + +void handle_pipe_in_parent(t_ast *command) +{ + ft_dup2(command->pipefd[0], STDIN_FILENO, "dup2 in pipe_parent"); + ft_close(command->pipefd[1], "close in pipe_parent"); + ft_close(command->pipefd[0], "close in pipe_parent"); +} diff --git a/ast/handle_heredoc.c b/ast/handle_heredoc.c new file mode 100644 index 0000000..8b42bd8 --- /dev/null +++ b/ast/handle_heredoc.c @@ -0,0 +1,85 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* handle_heredoc.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/21 11:15:25 by vvobis #+# #+# */ +/* Updated: 2025/02/15 14:59:42 by victor ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +void remove_quotes(char *s) +{ + uint i; + + i = 0; + if (!s) + return ; + while (s[i]) + { + if (s[i] == '\'' || s[i] == '\"') + { + ft_memmove(&s[i], &s[i] + 1, ft_strlen(&s[i])); + } + else + i++; + } +} + +void print_value(char *value, int fd) +{ + if (value && value[ft_strlen(value) - 1] == '\n') + value[ft_strlen(value) - (ft_strlen(value) > 0)] = 0; + ft_putendl_fd(value, fd); +} + +bool has_been_done_helper(t_token *token, char *value, \ + uint value_length, int fd) +{ + char *token_value; + bool has_been_done; + + has_been_done = false; + if (token->token_value) + { + token_value = token->token_value; + token->token_type = TOKEN_DONE; + while (token_value && *token_value) + { + if (*token_value++ == '\n') + { + if (ft_strncmp(token_value, value, value_length) == 0 \ + && (*(token_value + value_length) == '\n' \ + || *(token_value + value_length) == '\0')) + { + *token_value = 0; + has_been_done = true; + } + } + } + } + return (print_value(token->token_value, fd), has_been_done); +} + +bool heredoc_has_been_done(t_token *token, char *value, int fd) +{ + uint32_t value_length; + uint32_t i; + + i = 0; + while (token[i].token_type != TOKEN_NEWLINE \ + && token[i].token_type != TOKEN_EOL) + i++; + while ((token[i].token_type == TOKEN_NEWLINE \ + || token[i].token_type == TOKEN_DONE) \ + && token[i].token_type != TOKEN_EOL) + i++; + value_length = ft_strlen(value); + if (token[i].token_type == TOKEN_EOL) + return (false); + return (has_been_done_helper(&token[i], value, value_length, fd)); +} diff --git a/ast/handle_redirs.c b/ast/handle_redirs.c new file mode 100644 index 0000000..9939062 --- /dev/null +++ b/ast/handle_redirs.c @@ -0,0 +1,144 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* handle_redirs.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: andrejarama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/07/22 11:56:47 by anarama #+# #+# */ +/* Updated: 2025/02/15 14:59:25 by victor ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" +#include + +bool handle_temp(t_token *token) +{ + char *was_variable; + int32_t i; + char **temp; + + if (token->token_value && token->token_value[0] == '$') + was_variable = token->token_value; + else + was_variable = NULL; + temp = (char **)(char *[]){token->token_value, NULL}; + evaluate_input(&temp, &i, 0); + token->token_value = temp[0]; + if (was_variable) + if (temp[0][0] == 0) + return (p_stderr(2, \ + "minishell: %s: ambiguos redirect\n", was_variable), false); + return (true); +} + +void handle_redir_in(t_ast *branch, \ + t_token *token, \ + t_token *token_next) +{ + if (token->token_type == TOKEN_REDIRECT_IN) + { + if (branch->path_file_in == 0 \ + || ft_strncmp(token_next->token_value, branch->path_file_in, \ + ft_strlen(branch->path_file_in)) != 0) + { + if (handle_temp(token_next)) + { + if (branch->has_redir_in) + ft_close(branch->fd_in, "in hanlde_redir_in"); + branch->path_file_in = token_next->token_value; + ft_open(&branch->fd_in, branch->path_file_in, O_RDONLY, 0); + branch->has_redir_in = true; + if (branch->fd_in == -1) + branch->type = NODE_INVALID; + } + else + branch->type = NODE_INVALID; + } + token->token_type = TOKEN_DONE; + token_next->token_type = TOKEN_DONE; + } +} + +void handle_redir_out( t_ast *branch, \ + t_token *token, \ + t_token *token_next) +{ + if (token->token_type == TOKEN_REDIRECT_OUT) + { + if (branch->path_file_out == 0 \ + || ft_strncmp(token_next->token_value, branch->path_file_out, \ + ft_strlen(branch->path_file_out)) != 0) + { + if (handle_temp(token_next)) + { + if (branch->has_redir_out == true) + ft_close(branch->fd_out, "in branch redir_out"); + branch->path_file_out = token_next->token_value; + ft_open(&branch->fd_out, branch->path_file_out, \ + O_WRONLY | O_CREAT | O_TRUNC, 0644); + branch->has_redir_out = true; + if (branch->fd_out == -1) + branch->type = NODE_INVALID; + } + else + branch->type = NODE_INVALID; + } + token->token_type = TOKEN_DONE; + token_next->token_type = TOKEN_DONE; + } +} + +void handle_redir_append(t_ast *branch, \ + t_token *token, \ + t_token *token_next) +{ + if (token->token_type == TOKEN_REDIRECT_APPEND) + { + if (branch->path_file_out == 0 \ + || ft_strncmp(token_next->token_value, branch->path_file_out, \ + ft_strlen(branch->path_file_out)) != 0) + { + if (handle_temp(token_next)) + { + branch->path_file_out = token_next->token_value; + if (branch->has_redir_out == true) + ft_close(branch->fd_out, "in branch redir_out"); + ft_open(&branch->fd_out, branch->path_file_out, \ + O_WRONLY | O_CREAT | O_APPEND, 0644); + if (branch->fd_out == -1) + branch->type = NODE_INVALID; + branch->has_redir_out = true; + } + else + branch->type = NODE_INVALID; + } + token->token_type = TOKEN_DONE; + token_next->token_type = TOKEN_DONE; + } +} + +void handle_redir_heredoc( t_ast *branch, \ + t_token *token, \ + uint8_t token_id) +{ + if (token->token_type == TOKEN_HEREDOC) + { + branch->path_file_in = ft_strdup((char []){'.', '/', '.', 't', \ + 'm', 'p', token_id + 33, 0}); + branch->is_heredoc = true; + ft_open(&branch->fd_in, branch->path_file_in, O_CREAT | O_WRONLY, 0644); + remove_quotes(token[1].token_value); + if (!heredoc_has_been_done(token, \ + token[1].token_value, branch->fd_in) && isatty(0)) + { + token_heredoc_get(token, token[1].token_value); + print_value(token->token_value, branch->fd_in); + } + ft_close(branch->fd_in, "fd_in in heredoc"); + branch->has_redir_in = true; + token[0].token_type = TOKEN_DONE; + token[1].token_type = TOKEN_DONE; + } +} diff --git a/ast/parse_tokens.c b/ast/parse_tokens.c new file mode 100644 index 0000000..3131008 --- /dev/null +++ b/ast/parse_tokens.c @@ -0,0 +1,125 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* parse_tokens.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: anarama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/07/20 17:46:26 by anarama #+# #+# */ +/* Updated: 2024/08/27 15:04:45 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +static void parse_branch(t_token *tokens, t_ast *branch) +{ + int capacity; + int count; + uint32_t i; + + count = 0; + capacity = INITIAL_TOKEN_CAPACITY; + branch->args = ft_calloc(capacity + 1, sizeof(char *)); + if (!branch->args) + return (perror("calloc in parse tokens"), \ + lst_memory(NULL, NULL, CLEAN)); + i = -1; + while (!is_delimiter_token(&tokens[++i])) + { + if (tokens[i].token_type != TOKEN_DONE) + { + fill_args(&branch->args, count++, tokens[i].token_value, &capacity); + tokens[i].token_type = TOKEN_DONE; + } + } + if (tokens[i].token_type == TOKEN_EOL) + return ; + if (branch->type != NODE_INVALID) + branch->type = (t_node_type)tokens[i].token_type; + tokens[i].token_type = TOKEN_DONE; +} + +static t_ast collect_redirection(t_token *token, \ + int has_syntax_error) +{ + uint32_t i; + t_ast branch; + + i = 0; + branch = (t_ast){0}; + branch.fd_in = STDIN_FILENO; + branch.fd_out = STDOUT_FILENO; + while (!is_delimiter_token(&token[i]) && branch.type != NODE_INVALID) + { + if (token[i + 1].token_type == TOKEN_SEMICOLON) + token[i + 1].token_type = TOKEN_NEWLINE; + if (token[i + 1].token_type == TOKEN_WORD) + { + if (!has_syntax_error) + { + handle_redir_in(&branch, &token[i], &token[i + 1]); + handle_redir_out(&branch, &token[i], &token[i + 1]); + handle_redir_append(&branch, &token[i], &token[i + 1]); + } + } + if (has_syntax_error == 0) + handle_redir_heredoc(&branch, &token[i], i); + i++; + } + return (branch); +} + +void check_syntax_errors(t_token *token, int *error_catched) +{ + int i; + + i = 0; + while (token[i].token_type != TOKEN_NEWLINE \ + && token[i].token_type != TOKEN_EOL \ + && token[i].token_type != TOKEN_SEMICOLON \ + && *error_catched == 0) + { + if (token[i].token_type == TOKEN_REDIRECT_IN \ + || token[i].token_type == TOKEN_REDIRECT_OUT \ + || token[i].token_type == TOKEN_REDIRECT_APPEND \ + || token[i].token_type == TOKEN_HEREDOC) + check_valid_redir(token, i, error_catched); + else if (token[i].token_type == TOKEN_PIPE) + check_valid_pipe(token, i, error_catched); + else if (token[i].token_type == TOKEN_AND \ + || token[i].token_type == TOKEN_OR) + check_valid_logical_operator(token, i, error_catched); + i++; + } +} + +t_ast *parse_tokens( t_token *tokens, \ + int32_t *exit_status) +{ + t_ast *tree; + int i; + uint32_t tree_count; + int has_syntax_error; + + if (!tokens) + return (NULL); + i = 0; + tree_count = determine_trees(tokens); + tree = ft_calloc(tree_count + 1, sizeof(t_ast)); + lst_memory(tree, tree_destroy, ADD); + tree[tree_count].type = NODE_END; + has_syntax_error = false; + while (tree[i].type != NODE_END && !has_syntax_error) + { + check_syntax_errors(tokens, &has_syntax_error); + tree[i] = collect_redirection(tokens, has_syntax_error); + if (tree[i].type == NODE_INVALID) + *exit_status = 1; + parse_branch(tokens, &tree[i]); + i++; + } + if (has_syntax_error != false) + return (*exit_status = 2, lst_memory(tree, NULL, FREE), NULL); + return (tree); +} diff --git a/ast/parse_tokens_helper.c b/ast/parse_tokens_helper.c new file mode 100644 index 0000000..a6db23a --- /dev/null +++ b/ast/parse_tokens_helper.c @@ -0,0 +1,67 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* parse_tokens_helper.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/23 14:36:35 by vvobis #+# #+# */ +/* Updated: 2024/08/26 14:22:12 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +uint32_t determine_trees(t_token *tokens) +{ + uint32_t tree_count; + uint32_t i; + bool has_heredoc; + + i = 0; + tree_count = 1; + has_heredoc = false; + while (tokens[i].token_type != TOKEN_EOL) + { + if (tokens[i].token_type == TOKEN_HEREDOC) + has_heredoc = true; + if (is_delimiter_token(&tokens[i]) || \ + (tokens[i].token_type == TOKEN_NEWLINE && has_heredoc == true)) + { + has_heredoc = false; + tree_count++; + } + i++; + } + return (tree_count); +} + +void tree_destroy(void *tree_ptr) +{ + uint32_t i; + t_ast *tree; + + i = 0; + tree = (t_ast *)tree_ptr; + while (tree && tree[i].type != NODE_END) + { + if (tree[i].has_redir_out == true) + ft_close(tree[i].fd_out, "fd_out in tree_destroy"); + if (tree[i].is_heredoc) + ft_free(&tree->path_file_in); + if (tree[i].args) + ft_free(&tree[i].args); + i++; + } + ft_free(&tree); +} + +bool is_delimiter_token(t_token *token) +{ + return (token->token_type == TOKEN_EOL \ + || token->token_type == TOKEN_AND \ + || token->token_type == TOKEN_OR \ + || token->token_type == TOKEN_NEWLINE \ + || token->token_type == TOKEN_PIPE \ + || token->token_type == TOKEN_SEMICOLON); +} diff --git a/ast/parser.c b/ast/parser.c new file mode 100644 index 0000000..96be9e7 --- /dev/null +++ b/ast/parser.c @@ -0,0 +1,44 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* parser.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: anarama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/07/17 13:17:47 by anarama #+# #+# */ +/* Updated: 2024/08/10 22:20:35 by victor ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +void **custom_realloc(void ***args, int old_capacity, int new_capacity) +{ + void **new_args; + + new_args = ft_calloc(new_capacity + 1, sizeof(void *)); + if (!new_args) + { + perror("Malloc failed while reallocing memory"); + lst_memory(NULL, NULL, CLEAN); + } + ft_memcpy(new_args, *args, old_capacity * sizeof(void *)); + free(*args); + return (new_args); +} + +void fill_args(char ***args, int count, char *token_value, int *capacity) +{ + if (count >= *capacity) + { + *args = (char **)custom_realloc((void ***)args, + *capacity, *capacity * 2); + if (!args) + { + perror("calloc in parse tokens"); + lst_memory(NULL, NULL, CLEAN); + } + *capacity *= 2; + } + (*args)[count] = token_value; +} diff --git a/ast/syntax_check.c b/ast/syntax_check.c new file mode 100644 index 0000000..7a5b9d1 --- /dev/null +++ b/ast/syntax_check.c @@ -0,0 +1,117 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* syntax_check.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: anarama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/04 14:19:12 by anarama #+# #+# */ +/* Updated: 2024/08/26 14:18:42 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +void check_valid_redir_helper(t_token *token, int index, int *error_catched) +{ + if (token[index + 1].token_type == TOKEN_AND + || token[index + 1].token_type == TOKEN_OR) + { + print_error_logical_operator(token[index + 1].token_type); + *error_catched = 1; + } + else if (token[index + 1].token_type == TOKEN_PIPE) + return (print_error_pipe(), *error_catched = 1, (void)0); + else if (token[index + 1].token_type == TOKEN_REDIRECT_IN \ + || token[index + 1].token_type == TOKEN_REDIRECT_OUT \ + || token[index + 1].token_type == TOKEN_REDIRECT_APPEND \ + || token[index + 1].token_type == TOKEN_HEREDOC) + { + print_error_redir(token[index + 1].token_type); + *error_catched = 1; + } +} + +void check_valid_redir(t_token *token, int index, int *error_catched) +{ + if (token[index + 1].token_type == TOKEN_EOL \ + || token[index + 1].token_type == TOKEN_NEWLINE \ + || token[index + 1].token_type == 0 \ + || (token[index + 1].token_type == TOKEN_WORD \ + && token[index + 1].token_value == NULL)) + { + ft_putendl_fd(\ + "minishell: syntax error near unexpected token `newline'", 2); + *error_catched = 1; + } + check_valid_redir_helper(token, index, error_catched); +} + +void check_valid_pipe(t_token *token, int index, int *error_catched) +{ + if (index == 0 || token[index + 1].token_type == 0 \ + || token[index + 1].token_type == TOKEN_EOL + || (token[index + 1].token_type == TOKEN_WORD \ + && token[index + 1].token_value == NULL)) + { + print_error_pipe(); + *error_catched = 1; + } + else if (token[index + 1].token_type == TOKEN_AND + || token[index + 1].token_type == TOKEN_OR) + { + print_error_logical_operator(token[index + 1].token_type); + *error_catched = 1; + } + else if (token[index + 1].token_type == TOKEN_PIPE) + { + print_error_pipe(); + *error_catched = 1; + } +} + +void check_valid_logical_operator( t_token *token, \ + int index, \ + int *error_catched) +{ + if (index == 0 || token[index + 1].token_type == TOKEN_EOL \ + || token[index + 1].token_type == TOKEN_NEWLINE \ + || token[index + 1].token_type == 0) + { + print_error_logical_operator(token[index].token_type); + *error_catched = 1; + } + else if (token[index + 1].token_type == TOKEN_AND + || token[index + 1].token_type == TOKEN_OR) + { + print_error_logical_operator(token[index + 1].token_type); + *error_catched = 1; + } + else if (token[index + 1].token_type == TOKEN_PIPE) + { + print_error_pipe(); + *error_catched = 1; + } +} + +void check_valid_heredoc(t_token *token, int index, int *error_catched) +{ + if (token[index + 1].token_value == 0 \ + || *token[index + 1].token_value == 0 || token[index + 1].token_type == 0) + { + *error_catched = 2; + if (token[index + 1].token_type == TOKEN_AND \ + || token[index + 1].token_type == TOKEN_OR) + print_error_logical_operator(token[index].token_type); + else if (token[index + 1].token_type == TOKEN_PIPE) + print_error_pipe(); + else if (token[index + 1].token_type == TOKEN_REDIRECT_IN \ + || token[index + 1].token_type == TOKEN_REDIRECT_OUT \ + || token[index + 1].token_type == TOKEN_REDIRECT_APPEND \ + || token[index + 1].token_type == TOKEN_HEREDOC) + print_error_redir(token[index + 1].token_type); + else + ft_putendl_fd(\ + "minishell: syntax error near unexpected token `newline'", 2); + } +} diff --git a/ast/syntax_check_helper.c b/ast/syntax_check_helper.c new file mode 100644 index 0000000..3e3bd2c --- /dev/null +++ b/ast/syntax_check_helper.c @@ -0,0 +1,38 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* syntax_check_helper.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/23 14:38:50 by vvobis #+# #+# */ +/* Updated: 2024/08/23 14:40:12 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +void print_error_logical_operator(t_token_type token_type) +{ + if (token_type == TOKEN_AND) + ft_putendl_fd("minishell: syntax error near unexpected token `&&'", 2); + if (token_type == TOKEN_OR) + ft_putendl_fd("minishell: syntax error near unexpected token `||'", 2); +} + +void print_error_pipe(void) +{ + ft_putendl_fd("minishell: syntax error near unexpected token `|'", 2); +} + +void print_error_redir(t_token_type token_type) +{ + if (token_type == TOKEN_REDIRECT_APPEND) + ft_putendl_fd("minishell: syntax error near unexpected token `>>'", 2); + else if (token_type == TOKEN_REDIRECT_IN) + ft_putendl_fd("minishell: syntax error near unexpected token `<'", 2); + else if (token_type == TOKEN_REDIRECT_OUT) + ft_putendl_fd("minishell: syntax error near unexpected token `>'", 2); + else if (token_type == TOKEN_HEREDOC) + ft_putendl_fd("minishell: syntax error near unexpected token `<<'", 2); +} diff --git a/bin/minishell b/bin/minishell new file mode 100755 index 0000000..aec2af1 Binary files /dev/null and b/bin/minishell differ diff --git a/builtin/ft_cd.c b/builtin/ft_cd.c new file mode 100644 index 0000000..79dcaff --- /dev/null +++ b/builtin/ft_cd.c @@ -0,0 +1,71 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_cd.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/07/24 14:10:08 by vvobis #+# #+# */ +/* Updated: 2024/08/27 16:57:49 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +static void pwd_update(const char **environment) +{ + char *pwd; + char *old_pwd; + + pwd = getcwd(NULL, 0); + if (!pwd) + { + perror("getcwd"); + lst_memory(NULL, NULL, CLEAN); + } + old_pwd = environment_variable_value_get("PWD", environment); + environment_variable_value_change(environment, "OLDPWD", old_pwd); + environment_variable_value_change(environment, "PWD", pwd); + ft_free(&pwd); +} + +void cd_correct(char *args, const char **environment, int *exit_status) +{ + char *path; + + if (ft_memcmp(args, "-\0", 2) == 0) + { + path = environment_variable_value_get("OLDPWD", environment); + ft_putendl_fd(path, 1); + } + else + path = args; + if (chdir(path) != 0) + return (*exit_status = 1, ft_putstr_fd("minishell: cd: ", 2), \ + perror(path)); + *exit_status = 0; +} + +void ft_cd( const char **environment, \ + const char **args, \ + int32_t *exit_status) +{ + uint32_t args_size; + char *path; + + args_size = get_split_size((const char **)args); + if (args_size > 2) + return (*exit_status = 1, \ + ft_putendl_fd("minishell: cd: too many arguments", 2)); + else if (args_size == 1) + { + path = environment_variable_value_get("HOME", environment); + if (chdir(path) != 0) + return (*exit_status = 1, perror("cd")); + *exit_status = 0; + } + else + cd_correct((char *)args[1], environment, exit_status); + if (*exit_status == 0) + pwd_update((const char **)environment); +} diff --git a/builtin/ft_echo.c b/builtin/ft_echo.c new file mode 100644 index 0000000..9a28d30 --- /dev/null +++ b/builtin/ft_echo.c @@ -0,0 +1,110 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_echo.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/07/24 11:39:04 by vvobis #+# #+# */ +/* Updated: 2024/08/22 10:30:26 by victor ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +void trim_spaces(char *args) +{ + uint32_t i; + uint32_t j; + + i = 0; + if (!args) + return ; + while (args[i]) + { + j = i; + while (ft_isspace(args[j])) + j++; + ft_memmove(&args[i], &args[j - (j > i && i > 0)], \ + ft_strlen(&args[i]) + 1); + i++; + } +} + +bool is_dash_n(char *arg) +{ + uint32_t i; + + i = 0; + if (arg[i] && arg[i] == '-') + { + while (arg[i] && arg[++i] == 'n') + ; + if (arg[i] == 0) + return (true); + } + return (false); +} + +int32_t echo_no_newline(char **args) +{ + uint32_t i; + + i = 0; + while (args[i] && is_dash_n(args[i])) + i++; + while (args[i]) + { + ft_putstr_fd(args[i], 1); + if (*args[i] && args[i + 1]) + ft_putchar_fd(' ', 1); + i++; + } + return (0); +} + +int32_t echo_newline(char **args, bool is_single) +{ + uint32_t i; + + i = 0; + while (args[i + 1]) + { + if (is_single) + trim_spaces(args[i]); + ft_putstr_fd(args[i], 1); + ft_putchar_fd(' ', 1); + i++; + } + if (is_single) + trim_spaces(args[i]); + if (args[i] && args[i][ft_strlen(args[i]) - \ + (ft_strlen(args[i]) > 0)] == '\n') + ft_putstr_fd(args[i], 1); + else + ft_putendl_fd(args[i], 1); + return (0); +} + +int32_t ft_echo(char **args, int32_t *exit_status) +{ + uint32_t i; + + i = 0; + *exit_status = 0; + if (args[1]) + { + if (ft_memcmp(args[1], "-n", 2) == 0) + { + while (args[1][++i] == 'n') + ; + if (args[1][i] == 0) + return (echo_no_newline(&args[2]), *exit_status = 0); + } + echo_newline(&args[1], 0); + *exit_status = 0; + } + else + ft_putchar_fd('\n', 1); + return (0); +} diff --git a/builtin/ft_env.c b/builtin/ft_env.c new file mode 100644 index 0000000..631a243 --- /dev/null +++ b/builtin/ft_env.c @@ -0,0 +1,24 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_env.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/07/24 13:56:33 by vvobis #+# #+# */ +/* Updated: 2024/08/04 10:31:19 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +void ft_env(const char **environment, int32_t *exit_status) +{ + if (!environment) + *exit_status = 1; + else + { + *exit_status = 0; + environment_print(environment); + } +} diff --git a/builtin/ft_exit.c b/builtin/ft_exit.c new file mode 100644 index 0000000..62604b3 --- /dev/null +++ b/builtin/ft_exit.c @@ -0,0 +1,88 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_exit.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/07/24 16:52:07 by vvobis #+# #+# */ +/* Updated: 2025/02/15 14:59:55 by victor ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +bool check_exit_status(char *status) +{ + char *number_string; + int64_t number; + uint8_t is_too_big; + + if (!status || !*status) + return (false); + is_too_big = false; + while (*status && *status == '0') + status++; + if (*status == '+' || *status == '0') + status++; + number = ft_atol(status, &is_too_big); + if (is_too_big == true) + return (false); + number_string = ft_ltoa(number); + if (!number_string) + return (perror("malloc"), lst_memory(NULL, NULL, CLEAN), 0); + if (ft_strncmp(status, number_string, ft_strlen(status)) == 0) + return (ft_free(&number_string), true); + ft_free(&number_string); + return (false); +} + +bool exit_with_args( char **args, \ + bool *invalid_message_print, \ + uint32_t args_length, \ + int32_t *exit_status) +{ + *invalid_message_print = check_exit_status(args[1]); + if (*invalid_message_print && args_length == 2) + *exit_status = ft_atol(args[1], \ + (uint8_t *)invalid_message_print); + else if (!*invalid_message_print) + { + *exit_status = 2; + p_stderr(2, "minishell: exit: %s: numeric argument required\n", \ + args[1]); + } + else if (*invalid_message_print && args_length > 2) + return (ft_putendl_fd("minishell: exit: too many arguments", \ + 2), 1); + return (0); +} + +uint get_tree_size(t_ast *tree) +{ + uint i; + + i = 0; + while (tree[i].type != NODE_END) + i++; + return (i); +} + +void ft_exit(t_ast *tree, int *exit_status_prev) +{ + uint32_t args_length; + int32_t exit_status; + bool invalid_message_print; + + exit_status = *exit_status_prev; + args_length = get_split_size((const char **)tree->args); + invalid_message_print = false; + ft_putendl_fd("exit", 2); + if (args_length > 1) + if (exit_with_args(tree->args, &invalid_message_print, \ + args_length, &exit_status)) + return ; + wait_pids(tree, get_tree_size(tree), tree->cpid, NULL); + lst_memory(NULL, NULL, END); + exit(exit_status % 256); +} diff --git a/builtin/ft_export.c b/builtin/ft_export.c new file mode 100644 index 0000000..7093c69 --- /dev/null +++ b/builtin/ft_export.c @@ -0,0 +1,122 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_export.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/07/24 14:41:32 by vvobis #+# #+# */ +/* Updated: 2024/08/19 23:26:58 by victor ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" +#include +#include + +static void print_environment_a_la_export(char **env) +{ + char *variable_name; + char *variable_value; + uint32_t i; + + i = 0; + while (env[i]) + { + variable_name = env[i]; + variable_value = ft_strchr(variable_name, '='); + if (variable_value) + { + *variable_value++ = 0; + ft_printf("declare -x %s=\"%s\"\n", variable_name, variable_value); + *--variable_value = '='; + } + else + ft_printf("declare -x %s=\"\"\n", variable_name); + i++; + } +} + +static void environment_print_sorted(const char **environment) +{ + uint32_t i; + uint32_t length1; + char *tmp; + + i = 0; + while (environment[i] && environment[i + 1]) + { + tmp = ft_strchr(environment[i], '='); + if (!tmp) + tmp = ft_strchr(environment[i], 0); + length1 = tmp - environment[i]; + if (ft_strncmp(environment[i], environment[i + 1], length1) > 0) + { + tmp = (char *)environment[i]; + environment[i] = environment[i + 1]; + environment[i + 1] = tmp; + environment_print_sorted(environment); + break ; + } + i++; + } + if (environment[i + 1] == NULL) + print_environment_a_la_export((char **)environment); +} + +static void print_sorted(const char **environment) +{ + char **env; + uint32_t i; + + env = ft_calloc(get_split_size(environment) + 1, sizeof(*env)); + if (!env) + return (perror("malloc"), lst_memory(NULL, NULL, CLEAN)); + i = -1; + while (environment[++i]) + env[i] = (char *)environment[i]; + environment_print_sorted((const char **)env); + ft_free(&env); +} + +bool is_allowed_char(const char *s) +{ + uint32_t i; + + i = 0; + if (!ft_isalpha(s[i]) && s[i] != '_') + return (false); + i++; + while (s[i] && (ft_isalnum(s[i]) || s[i] == '_')) + i++; + if (s[i] == '=' || s[i] == 0) + return (true); + return (false); +} + +void ft_export(const char **args, int32_t *exit_status) +{ + uint32_t i; + char *variable_name; + char *variable_value; + char **environment; + + environment = env_static(NULL); + if (get_split_size(args) < 2) + return (print_sorted((const char **)environment)); + i = 1; + while (args[i]) + { + if (!is_allowed_char(args[i])) + return (p_stderr(2, \ + "minishell: export: `%s': not a valid identifier\n", \ + args[i]), *exit_status = 1, (void)0); + variable_name = (char *)args[i]; + variable_value = ft_strchr(args[i], '='); + if (variable_value) + *variable_value++ = 0; + environment_variable_add(&environment, variable_name, variable_value); + i++; + } + *exit_status = 0; +} diff --git a/builtin/ft_pwd.c b/builtin/ft_pwd.c new file mode 100644 index 0000000..80f7cab --- /dev/null +++ b/builtin/ft_pwd.c @@ -0,0 +1,28 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_pwd.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: victor +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/07/24 22:49:03 by victor #+# #+# */ +/* Updated: 2024/08/16 23:50:58 by victor ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +void ft_pwd(const char **environment, int32_t *exit_status) +{ + char *pwd; + + if (!environment) + *exit_status = 1; + else + { + *exit_status = 0; + pwd = getcwd(NULL, 0); + ft_putendl_fd(pwd, 1); + ft_free(&pwd); + } +} diff --git a/builtin/ft_unset.c b/builtin/ft_unset.c new file mode 100644 index 0000000..969f273 --- /dev/null +++ b/builtin/ft_unset.c @@ -0,0 +1,33 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_unset.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/07/24 14:29:41 by vvobis #+# #+# */ +/* Updated: 2024/08/10 22:25:27 by victor ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +void ft_unset(char **envivonment, const char **args, int32_t *exit_status) +{ + uint32_t args_size; + uint32_t i; + + args_size = get_split_size(args); + if (args_size < 2) + return ; + else if (args[1] && *args[1] == '-') + return (ft_putendl_fd("unset: usage: unset [name ...]", \ + *exit_status = 2)); + i = 1; + while (args[i]) + { + environment_variable_remove(envivonment, args[i]); + i++; + } + *exit_status = 0; +} diff --git a/libft/Makefile b/libft/Makefile new file mode 100644 index 0000000..462523a --- /dev/null +++ b/libft/Makefile @@ -0,0 +1,40 @@ +NAME := libft.a +CC := cc +CFLAGS:= -Wall -Wextra -Werror -g3 +SRC := ft_bzero.c ft_isalnum.c ft_isalpha.c ft_isdigit.c \ + ft_isprint.c ft_memcpy.c ft_memmove.c ft_memset.c \ + ft_strlcat.c ft_strlcpy.c ft_strlen.c \ + ft_isascii.c ft_strchr.c ft_strrchr.c ft_strncmp.c \ + ft_toupper.c ft_tolower.c ft_memchr.c ft_strnstr.c \ + ft_atoi.c ft_memcmp.c ft_calloc.c ft_strdup.c \ + ft_substr.c ft_strjoin.c ft_strtrim.c ft_split.c \ + ft_itoa.c ft_strmapi.c ft_striteri.c ft_putchar_fd.c \ + ft_putstr_fd.c ft_putendl_fd.c ft_putnbr_fd.c \ + get_next_line.c get_next_line_utils.c ft_puthex.c \ + ft_printf.c ft_putascii.c ft_putptr.c ft_free.c \ + ft_atol.c ft_ltoa.c +SRCBON := ft_lstnew_bonus.c ft_lstadd_front_bonus.c ft_lstsize_bonus.c ft_lstlast_bonus.c ft_lstadd_back_bonus.c ft_lstdelone_bonus.c ft_lstclear_bonus.c ft_lstiter_bonus.c ft_lstmap_bonus.c + +OBJBON := $(SRC:%.c=%.o) $(SRCBON:%.c=%.o) + +OBJ := $(SRC:%.c=%.o) + +all: $(NAME) + +bonus: $(OBJBON) + ar rcs libft.a $(OBJ) $(OBJBON) + +$(NAME): $(OBJ) + ar rcs libft.a $(OBJ) + +$(OBJ): $(SRC) + $(CC) -c $(CFLAGS) $(SRC) + +re: fclean all + +fclean: clean + rm -f $(NAME) + +clean: + rm -f $(OBJ) $(OBJBON) + diff --git a/libft/ft_atoi.c b/libft/ft_atoi.c new file mode 100644 index 0000000..b2bb953 --- /dev/null +++ b/libft/ft_atoi.c @@ -0,0 +1,42 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_atoi.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/10 10:49:04 by vvobis #+# #+# */ +/* Updated: 2024/08/17 21:39:08 by victor ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +int is_space(char const c) +{ + if ((c >= 9 && c <= 13) || c == ' ') + return (1); + return (0); +} + +int ft_atoi(char const *s) +{ + int nb; + char const *tmp; + + nb = 0; + while (is_space(*s)) + s++; + tmp = s; + if (*tmp == '+' || *tmp == '-') + tmp++; + while (*tmp >= '0' && *tmp <= '9') + { + nb *= 10; + nb += (*tmp - '0'); + tmp++; + } + if (*s == '-') + nb = -nb; + return (nb); +} diff --git a/libft/ft_atol.c b/libft/ft_atol.c new file mode 100644 index 0000000..b037ae3 --- /dev/null +++ b/libft/ft_atol.c @@ -0,0 +1,37 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_atol.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/10 10:49:04 by vvobis #+# #+# */ +/* Updated: 2024/08/26 21:00:15 by victor ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +long ft_atol(char const *s, uint8_t *too_big) +{ + unsigned long long nb; + char const *tmp; + + nb = 0; + while (is_space(*s)) + s++; + tmp = s; + if (*tmp == '+' || *tmp == '-') + tmp++; + while (*tmp >= '0' && *tmp <= '9') + { + nb *= 10; + nb += (*tmp - '0'); + tmp++; + if (nb > (uint64_t)LLONG_MAX + (*s == '-')) + return (*too_big == 1); + } + if (*s == '-') + nb = -nb; + return (nb); +} diff --git a/libft/ft_bzero.c b/libft/ft_bzero.c new file mode 100644 index 0000000..332517f --- /dev/null +++ b/libft/ft_bzero.c @@ -0,0 +1,19 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_bzero.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/02 16:04:55 by vvobis #+# #+# */ +/* Updated: 2024/04/09 20:54:53 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void ft_bzero(void *s, size_t n) +{ + while (n--) + *(char *)s++ = 0; +} diff --git a/libft/ft_calloc.c b/libft/ft_calloc.c new file mode 100644 index 0000000..dcef84c --- /dev/null +++ b/libft/ft_calloc.c @@ -0,0 +1,30 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_calloc.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/04 13:44:00 by vvobis #+# #+# */ +/* Updated: 2024/04/10 16:39:56 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void *ft_calloc(size_t n, size_t s) +{ + char *tmp; + unsigned long i; + + i = 0; + if (n == 0) + return (malloc(0)); + if (SIZE_MAX / n < s) + return (NULL); + tmp = malloc(n * s); + if (tmp) + while (i < n * s) + tmp[i++] = 0; + return ((void *)tmp); +} diff --git a/libft/ft_free.c b/libft/ft_free.c new file mode 100644 index 0000000..79f2dfb --- /dev/null +++ b/libft/ft_free.c @@ -0,0 +1,19 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_free.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/13 15:23:16 by vvobis #+# #+# */ +/* Updated: 2024/08/10 22:39:49 by victor ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void ft_free(void *ptr) +{ + free(*(void **)ptr); + *(void **)ptr = NULL; +} diff --git a/libft/ft_isalnum.c b/libft/ft_isalnum.c new file mode 100644 index 0000000..2abb4a5 --- /dev/null +++ b/libft/ft_isalnum.c @@ -0,0 +1,20 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_isalnum.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/02 15:59:18 by vvobis #+# #+# */ +/* Updated: 2024/04/02 15:59:23 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +int ft_isalnum(int c) +{ + if (ft_isdigit(c) || ft_isalpha(c)) + return (1); + return (0); +} diff --git a/libft/ft_isalpha.c b/libft/ft_isalpha.c new file mode 100644 index 0000000..1dfab51 --- /dev/null +++ b/libft/ft_isalpha.c @@ -0,0 +1,20 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_isalpha.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/02 15:59:49 by vvobis #+# #+# */ +/* Updated: 2024/04/02 16:00:04 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +int ft_isalpha(int c) +{ + if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) + return (1); + return (0); +} diff --git a/libft/ft_isascii.c b/libft/ft_isascii.c new file mode 100644 index 0000000..0693407 --- /dev/null +++ b/libft/ft_isascii.c @@ -0,0 +1,20 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_isascii.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/02 19:48:35 by vvobis #+# #+# */ +/* Updated: 2024/04/02 19:49:36 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +int ft_isascii(int c) +{ + if (c >= 0 && c <= 127) + return (1); + return (0); +} diff --git a/libft/ft_isdigit.c b/libft/ft_isdigit.c new file mode 100644 index 0000000..4dd21ff --- /dev/null +++ b/libft/ft_isdigit.c @@ -0,0 +1,18 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_isdigit.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/02 16:14:56 by vvobis #+# #+# */ +/* Updated: 2024/04/02 19:38:45 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +int ft_isdigit(int c) +{ + if (c >= '0' && c <= '9') + return (1); + return (0); +} diff --git a/libft/ft_isprint.c b/libft/ft_isprint.c new file mode 100644 index 0000000..99da20a --- /dev/null +++ b/libft/ft_isprint.c @@ -0,0 +1,18 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_isprint.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/02 16:00:49 by vvobis #+# #+# */ +/* Updated: 2024/04/02 16:00:52 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +int ft_isprint(int c) +{ + if (c >= 32 && c <= 126) + return (1); + return (0); +} diff --git a/libft/ft_itoa.c b/libft/ft_itoa.c new file mode 100644 index 0000000..f973b4a --- /dev/null +++ b/libft/ft_itoa.c @@ -0,0 +1,75 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_itoa.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/05 20:16:48 by vvobis #+# #+# */ +/* Updated: 2024/04/11 14:48:59 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +static int get_len(int n) +{ + int i; + + if (n < 0) + n = -n; + i = 0; + while (n) + { + i++; + n /= 10; + } + return (i); +} + +static char *is_negative(int n) +{ + int i; + char *num; + + i = get_len(n); + num = malloc(sizeof(*num) * i + 2); + if (!num) + return (NULL); + num[i + 1] = 0; + while (n) + { + num[i--] = -(n % 10) + 48; + n /= 10; + } + num[i] = 0x2d; + return (num); +} + +static char *is_positive(int n) +{ + int i; + char *num; + + i = get_len(n); + num = malloc(sizeof(*num) * i + 1); + if (!num) + return (NULL); + num[i--] = 0; + while (n) + { + num[i--] = (n % 10) + 48; + n /= 10; + } + return (num); +} + +char *ft_itoa(int n) +{ + if (n == 0) + return (ft_strdup("0")); + else if (n < 0) + return (is_negative(n)); + else + return (is_positive(n)); +} diff --git a/libft/ft_lstadd_back_bonus.c b/libft/ft_lstadd_back_bonus.c new file mode 100644 index 0000000..f3d6959 --- /dev/null +++ b/libft/ft_lstadd_back_bonus.c @@ -0,0 +1,30 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_lstadd_back.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/09 13:51:32 by vvobis #+# #+# */ +/* Updated: 2024/04/09 18:17:12 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void ft_lstadd_back(t_list **lst, t_list *new) +{ + t_list *tmp; + + if (!new) + return ; + if (*lst) + { + tmp = *lst; + while (tmp->next) + tmp = tmp->next; + tmp->next = new; + } + else + *lst = new; +} diff --git a/libft/ft_lstadd_front_bonus.c b/libft/ft_lstadd_front_bonus.c new file mode 100644 index 0000000..25714f7 --- /dev/null +++ b/libft/ft_lstadd_front_bonus.c @@ -0,0 +1,26 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_lstadd_front.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/09 12:53:08 by vvobis #+# #+# */ +/* Updated: 2024/04/09 18:17:50 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void ft_lstadd_front(t_list **lst, t_list *new) +{ + if (!lst || !new) + return ; + if (!*lst) + *lst = new; + else + { + new->next = *lst; + *lst = new; + } +} diff --git a/libft/ft_lstclear_bonus.c b/libft/ft_lstclear_bonus.c new file mode 100644 index 0000000..8f531fb --- /dev/null +++ b/libft/ft_lstclear_bonus.c @@ -0,0 +1,28 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_lstclear.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/09 15:44:23 by vvobis #+# #+# */ +/* Updated: 2024/04/09 22:35:41 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void ft_lstclear(t_list **lst, void (*del)(void *)) +{ + t_list *tmp; + + if (!*lst || !del || !lst) + return ; + while (*lst) + { + tmp = (*lst)->next; + del((*lst)->content); + free(*lst); + *lst = tmp; + } +} diff --git a/libft/ft_lstdelone_bonus.c b/libft/ft_lstdelone_bonus.c new file mode 100644 index 0000000..c31153b --- /dev/null +++ b/libft/ft_lstdelone_bonus.c @@ -0,0 +1,21 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_lstdelone.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/09 14:24:03 by vvobis #+# #+# */ +/* Updated: 2024/04/09 15:42:04 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void ft_lstdelone(t_list *lst, void (*del)(void *)) +{ + if (!lst || !del) + return ; + del(lst->content); + free(lst); +} diff --git a/libft/ft_lstiter_bonus.c b/libft/ft_lstiter_bonus.c new file mode 100644 index 0000000..c38b240 --- /dev/null +++ b/libft/ft_lstiter_bonus.c @@ -0,0 +1,24 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_lstiter.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/09 15:57:51 by vvobis #+# #+# */ +/* Updated: 2024/04/09 18:20:05 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void ft_lstiter(t_list *lst, void (*f)(void *)) +{ + if (!lst || !f) + return ; + while (lst) + { + f(lst->content); + lst = lst->next; + } +} diff --git a/libft/ft_lstlast_bonus.c b/libft/ft_lstlast_bonus.c new file mode 100644 index 0000000..c83f4b0 --- /dev/null +++ b/libft/ft_lstlast_bonus.c @@ -0,0 +1,22 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_lstlast.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/09 13:47:08 by vvobis #+# #+# */ +/* Updated: 2024/04/09 15:11:51 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +t_list *ft_lstlast(t_list *lst) +{ + if (!lst) + return (NULL); + while (lst->next) + lst = lst->next; + return (lst); +} diff --git a/libft/ft_lstmap_bonus.c b/libft/ft_lstmap_bonus.c new file mode 100644 index 0000000..9cfc0c5 --- /dev/null +++ b/libft/ft_lstmap_bonus.c @@ -0,0 +1,44 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_lstmap.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/09 16:18:03 by vvobis #+# #+# */ +/* Updated: 2024/04/09 23:40:57 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +static void *free_list(t_list **head, void (*del)(void *), void *fcontent) +{ + if (fcontent) + del(fcontent); + ft_lstclear(head, del); + return (NULL); +} + +t_list *ft_lstmap(t_list *lst, void *(*f)(void *), void (*del)(void *)) +{ + t_list *tmp; + t_list *head; + void *fcontent; + + if (!lst || !f || !del) + return (NULL); + head = NULL; + while (lst) + { + fcontent = f(lst->content); + if (!fcontent) + return (free_list(&head, del, fcontent)); + tmp = ft_lstnew(fcontent); + if (!tmp) + return (free_list(&head, del, fcontent)); + ft_lstadd_back(&head, tmp); + lst = lst->next; + } + return (head); +} diff --git a/libft/ft_lstnew_bonus.c b/libft/ft_lstnew_bonus.c new file mode 100644 index 0000000..08775c5 --- /dev/null +++ b/libft/ft_lstnew_bonus.c @@ -0,0 +1,25 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_lstnew.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/09 11:10:05 by vvobis #+# #+# */ +/* Updated: 2024/04/09 18:59:48 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +t_list *ft_lstnew(void *content) +{ + t_list *tmp; + + tmp = malloc(sizeof(*tmp)); + if (!tmp) + return (NULL); + tmp->next = NULL; + tmp->content = content; + return (tmp); +} diff --git a/libft/ft_lstsize_bonus.c b/libft/ft_lstsize_bonus.c new file mode 100644 index 0000000..c8def02 --- /dev/null +++ b/libft/ft_lstsize_bonus.c @@ -0,0 +1,28 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_lstsize.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/09 13:43:08 by vvobis #+# #+# */ +/* Updated: 2024/04/09 18:21:11 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +int ft_lstsize(t_list *lst) +{ + int i; + + if (!lst) + return (0); + i = 1; + while (lst->next) + { + lst = lst->next; + i++; + } + return (i); +} diff --git a/libft/ft_ltoa.c b/libft/ft_ltoa.c new file mode 100644 index 0000000..fcb7d30 --- /dev/null +++ b/libft/ft_ltoa.c @@ -0,0 +1,75 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_ltoi.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/05 20:16:48 by vvobis #+# #+# */ +/* Updated: 2024/08/23 15:54:04 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +static int get_len(long long n) +{ + int i; + + if (n < 0) + n = -n; + i = 0; + while (n) + { + i++; + n /= 10; + } + return (i); +} + +static char *is_negative(long long n) +{ + int i; + char *num; + + i = get_len(n); + num = malloc(sizeof(*num) * i + 2); + if (!num) + return (NULL); + num[i + 1] = 0; + while (n) + { + num[i--] = -(n % 10) + 48; + n /= 10; + } + num[i] = 0x2d; + return (num); +} + +static char *is_positive(long long n) +{ + int i; + char *num; + + i = get_len(n); + num = malloc(sizeof(*num) * i + 1); + if (!num) + return (NULL); + num[i--] = 0; + while (n) + { + num[i--] = (n % 10) + 48; + n /= 10; + } + return (num); +} + +char *ft_ltoa(long long n) +{ + if (n == 0) + return (ft_strdup("0")); + else if (n < 0) + return (is_negative(n)); + else + return (is_positive(n)); +} diff --git a/libft/ft_memchr.c b/libft/ft_memchr.c new file mode 100644 index 0000000..3944037 --- /dev/null +++ b/libft/ft_memchr.c @@ -0,0 +1,31 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_memchr.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/03 15:13:59 by vvobis #+# #+# */ +/* Updated: 2024/04/09 20:55:24 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void *ft_memchr(void *s, int c, size_t n) +{ + unsigned char *p; + size_t i; + + i = 0; + p = (unsigned char *)s; + while (i < n) + { + if (p[i] == (unsigned char)c) + return ((void *)&p[i]); + i++; + } + if (p[i - 1] == (unsigned char)c) + return ((void *)&p[i]); + return (NULL); +} diff --git a/libft/ft_memcmp.c b/libft/ft_memcmp.c new file mode 100644 index 0000000..54180dc --- /dev/null +++ b/libft/ft_memcmp.c @@ -0,0 +1,31 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_memcmp.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/03 15:27:15 by vvobis #+# #+# */ +/* Updated: 2024/04/09 19:21:02 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +int ft_memcmp(void *s1, void const *s2, size_t n) +{ + unsigned char *p1; + unsigned char *p2; + unsigned int i; + + p1 = (unsigned char *)s1; + p2 = (unsigned char *)s2; + i = 0; + while (i < n) + { + if (p1[i] != p2[i]) + return (p1[i] - p2[i]); + i++; + } + return (0); +} diff --git a/libft/ft_memcpy.c b/libft/ft_memcpy.c new file mode 100644 index 0000000..e1e524a --- /dev/null +++ b/libft/ft_memcpy.c @@ -0,0 +1,32 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_memcpy.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/02 17:13:18 by vvobis #+# #+# */ +/* Updated: 2024/04/09 19:21:29 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void *ft_memcpy(void *dest, void const *src, size_t n) +{ + char *d; + char *s; + + if (n == 0 || (dest == NULL && src == NULL)) + return (dest); + if (dest == NULL || src == NULL) + { + *(char *)dest = 1; + *(char *)src = 1; + } + d = (char *) dest; + s = (char *) src; + while (n--) + *d++ = *s++; + return (dest); +} diff --git a/libft/ft_memmove.c b/libft/ft_memmove.c new file mode 100644 index 0000000..d5c700f --- /dev/null +++ b/libft/ft_memmove.c @@ -0,0 +1,30 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_memmove.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/02 17:42:28 by vvobis #+# #+# */ +/* Updated: 2024/04/09 19:21:54 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void *ft_memmove(void *dest, void const *src, size_t n) +{ + unsigned char *d; + unsigned char *s; + + if (!dest && !src) + return (dest); + d = (unsigned char *)dest; + s = (unsigned char *)src; + if (s < d) + while (n--) + d[n] = s[n]; + else + ft_memcpy(dest, (void *)src, n); + return (dest); +} diff --git a/libft/ft_memset.c b/libft/ft_memset.c new file mode 100644 index 0000000..792867a --- /dev/null +++ b/libft/ft_memset.c @@ -0,0 +1,23 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_memset.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/02 15:57:27 by vvobis #+# #+# */ +/* Updated: 2024/04/03 11:18:10 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void *ft_memset(void *s, int c, size_t n) +{ + char *str; + + str = (char *)s; + while (n--) + str[n] = c; + return (s); +} diff --git a/libft/ft_printf.c b/libft/ft_printf.c new file mode 100644 index 0000000..612f189 --- /dev/null +++ b/libft/ft_printf.c @@ -0,0 +1,61 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_printf.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/18 17:50:35 by vvobis #+# #+# */ +/* Updated: 2024/04/26 16:54:14 by victor ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "ft_printf.h" + +int handle_arg(va_list args, char format, int *count) +{ + if (format == 'd' || format == 'i') + ft_putnbr(va_arg(args, int), count); + else if (format == 'u') + ft_putnbr(va_arg(args, unsigned int), count); + else if (format == 's') + ft_putstr(va_arg(args, char *), count); + else if (format == 'X') + ft_puthex_upper(va_arg(args, unsigned int), count); + else if (format == 'x') + ft_puthex_lower(va_arg(args, unsigned int), count); + else if (format == 'p') + ft_putptr(va_arg(args, void *), count); + else if (format == 'c') + ft_putchar(va_arg(args, int), count); + else if (format == '%') + ft_putchar('%', count); + else + return (0); + return (1); +} + +int ft_printf(const char *format, ...) +{ + va_list args; + int count; + + if (!format) + return (-1); + va_start(args, format); + count = 0; + while (1) + { + while (*format != '%' && *format) + ft_putchar(*format++, &count); + if (!*format) + break ; + else + format++; + if (!*format || !handle_arg(args, *format, &count)) + return (-1); + format++; + } + va_end(args); + return (count); +} diff --git a/libft/ft_printf.h b/libft/ft_printf.h new file mode 100644 index 0000000..fc6a5bd --- /dev/null +++ b/libft/ft_printf.h @@ -0,0 +1,29 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_printf.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/18 12:50:35 by vvobis #+# #+# */ +/* Updated: 2024/04/18 20:47:09 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef FT_PRINTF_H + +# define FT_PRINTF_H + +# include +# include +# include + +int ft_printf(const char *format, ...); +void ft_puthex_lower(unsigned long nbr, int *count); +void ft_puthex_upper(unsigned long nbr, int *count); +void ft_putchar(int c, int *count); +void ft_putnbr(long n, int *count); +void ft_putstr(const char *str, int *count); +void ft_putptr(void *ptr, int *count); + +#endif diff --git a/libft/ft_putascii.c b/libft/ft_putascii.c new file mode 100644 index 0000000..248296c --- /dev/null +++ b/libft/ft_putascii.c @@ -0,0 +1,44 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_putascii.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/18 17:54:53 by vvobis #+# #+# */ +/* Updated: 2024/04/18 17:55:04 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "ft_printf.h" + +void ft_putchar(int c, int *count) +{ + write(1, &c, 1); + *count += 1; +} + +void ft_putnbr(long n, int *count) +{ + if (n < 0) + ft_putchar(0x2d, count); + if (n <= -10) + ft_putnbr(n / -10, count); + if (n >= 10) + ft_putnbr(n / 10, count); + if (n >= 0) + ft_putchar(n % 10 + 0x30, count); + if (n < 0) + ft_putchar(-(n % -10) + 0x30, count); +} + +void ft_putstr(const char *str, int *count) +{ + if (!str) + { + *count += ft_printf("(null)"); + return ; + } + while (*str) + ft_putchar(*str++, count); +} diff --git a/libft/ft_putchar_fd.c b/libft/ft_putchar_fd.c new file mode 100644 index 0000000..6b5d51f --- /dev/null +++ b/libft/ft_putchar_fd.c @@ -0,0 +1,18 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_putchar_fd.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/07 17:34:30 by vvobis #+# #+# */ +/* Updated: 2024/04/07 17:53:33 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void ft_putchar_fd(char c, int fd) +{ + write(fd, &c, 1); +} diff --git a/libft/ft_putendl_fd.c b/libft/ft_putendl_fd.c new file mode 100644 index 0000000..1c7d3b4 --- /dev/null +++ b/libft/ft_putendl_fd.c @@ -0,0 +1,21 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_putendl_fd.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/07 17:57:33 by vvobis #+# #+# */ +/* Updated: 2024/04/07 18:00:49 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void ft_putendl_fd(char *str, int fd) +{ + if (!str) + return ; + ft_putstr_fd(str, fd); + ft_putchar_fd(0x0a, fd); +} diff --git a/libft/ft_puthex.c b/libft/ft_puthex.c new file mode 100644 index 0000000..2f3e6d7 --- /dev/null +++ b/libft/ft_puthex.c @@ -0,0 +1,33 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_puthex.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/18 17:52:38 by vvobis #+# #+# */ +/* Updated: 2024/04/18 20:46:13 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "ft_printf.h" + +void ft_puthex_upper(unsigned long nbr, int *count) +{ + char *base_str; + + base_str = "0123456789ABCDEF"; + if (nbr >= 16) + ft_puthex_upper(nbr / 16, count); + ft_putchar(base_str[(nbr % 16)], count); +} + +void ft_puthex_lower(unsigned long nbr, int *count) +{ + char *base_str; + + base_str = "0123456789abcdef"; + if (nbr >= 16) + ft_puthex_lower(nbr / 16, count); + ft_putchar(base_str[(nbr % 16)], count); +} diff --git a/libft/ft_putnbr_fd.c b/libft/ft_putnbr_fd.c new file mode 100644 index 0000000..5073c24 --- /dev/null +++ b/libft/ft_putnbr_fd.c @@ -0,0 +1,27 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_putnbr_fd.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/07 18:02:14 by vvobis #+# #+# */ +/* Updated: 2024/04/11 11:23:10 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void ft_putnbr_fd(int n, int fd) +{ + if (n < 0) + ft_putchar_fd(0x2d, fd); + if (n <= -10) + ft_putnbr_fd(n / -10, fd); + if (n >= 10) + ft_putnbr_fd(n / 10, fd); + if (n >= 0) + ft_putchar_fd(n % 10 + 0x30, fd); + if (n < 0) + ft_putchar_fd(-(n % -10) + 0x30, fd); +} diff --git a/libft/ft_putptr.c b/libft/ft_putptr.c new file mode 100644 index 0000000..4d97d32 --- /dev/null +++ b/libft/ft_putptr.c @@ -0,0 +1,27 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_putptr.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/18 17:53:53 by vvobis #+# #+# */ +/* Updated: 2024/04/18 20:44:46 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "ft_printf.h" + +void ft_putptr(void *ptr, int *count) +{ + void **to_print; + + if (!ptr) + { + *count += ft_printf("(nil)"); + return ; + } + to_print = &ptr; + *count += ft_printf("0x"); + ft_puthex_lower((long)*to_print, count); +} diff --git a/libft/ft_putstr_fd.c b/libft/ft_putstr_fd.c new file mode 100644 index 0000000..4109811 --- /dev/null +++ b/libft/ft_putstr_fd.c @@ -0,0 +1,21 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_putstr_fd.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/07 17:48:41 by vvobis #+# #+# */ +/* Updated: 2024/07/31 10:01:48 by victor ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void ft_putstr_fd(const char *str, int fd) +{ + if (!str) + return ; + while (*str) + ft_putchar_fd(*str++, fd); +} diff --git a/libft/ft_split.c b/libft/ft_split.c new file mode 100644 index 0000000..b7568e5 --- /dev/null +++ b/libft/ft_split.c @@ -0,0 +1,84 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_split.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/05 20:14:20 by vvobis #+# #+# */ +/* Updated: 2024/06/14 16:06:51 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +static int count(char const *s, char const c) +{ + int n; + + n = 0; + if (*s != c && *s) + n = 1; + while (*s) + { + if (*s == c && *(s + 1) != c && *(s + 1)) + n++; + s++; + } + return (n); +} + +static int count_sub(char const *s, char const c) +{ + int i; + + i = 0; + while (*s != c && *s) + { + i++; + s++; + } + return (i); +} + +static char **free_all(char **back) +{ + char **tmp; + + tmp = back; + while (*back) + { + free(*back); + back++; + } + free(tmp); + return (NULL); +} + +char **ft_split(char const *s, char const c) +{ + char **tmp; + char **back; + + if (!s) + return (NULL); + tmp = (char **)ft_calloc(sizeof(*tmp), count(s, c) + 1); + if (!tmp) + return (NULL); + back = tmp; + while (*s && tmp) + { + while (*s == c && *s) + s++; + if (*s) + { + *tmp = ft_substr(s, 0, count_sub(s, c)); + if (!*tmp) + return (free_all(back)); + } + tmp++; + while (*s != c && *s) + s++; + } + return (back); +} diff --git a/libft/ft_strchr.c b/libft/ft_strchr.c new file mode 100644 index 0000000..30d0b93 --- /dev/null +++ b/libft/ft_strchr.c @@ -0,0 +1,29 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strchr.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/03 12:20:50 by vvobis #+# #+# */ +/* Updated: 2024/04/09 20:54:14 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +char *ft_strchr(char const *s, int c) +{ + int i; + + i = 0; + while (s[i]) + { + if (s[i] == (char)c) + return ((char *)&s[i]); + i++; + } + if ((char)c == 0) + return ((char *)&s[i]); + return (NULL); +} diff --git a/libft/ft_strdup.c b/libft/ft_strdup.c new file mode 100644 index 0000000..941d91b --- /dev/null +++ b/libft/ft_strdup.c @@ -0,0 +1,31 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strdup.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/04 18:44:05 by vvobis #+# #+# */ +/* Updated: 2024/04/12 10:44:23 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +char *ft_strdup(char const *s) +{ + char *tmp; + int i; + + i = 0; + tmp = ft_calloc(ft_strlen(s) + 1, sizeof(*tmp)); + if (!tmp) + return (NULL); + while (s[i]) + { + tmp[i] = s[i]; + i++; + } + tmp[i] = 0; + return (tmp); +} diff --git a/libft/ft_striteri.c b/libft/ft_striteri.c new file mode 100644 index 0000000..8aac9ae --- /dev/null +++ b/libft/ft_striteri.c @@ -0,0 +1,27 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_striteri.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/07 17:24:08 by vvobis #+# #+# */ +/* Updated: 2024/04/09 19:27:07 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void ft_striteri(char const *s, void (*f)(unsigned int, char *)) +{ + unsigned int i; + + if (!s || !f) + return ; + i = 0; + while (s[i]) + { + f(i, (char *)&s[i]); + i++; + } +} diff --git a/libft/ft_strjoin.c b/libft/ft_strjoin.c new file mode 100644 index 0000000..03be413 --- /dev/null +++ b/libft/ft_strjoin.c @@ -0,0 +1,41 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strjoin.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/04 19:08:03 by vvobis #+# #+# */ +/* Updated: 2024/04/12 10:07:26 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +char *ft_strjoin(char const *s1, char const *s2) +{ + char *tmp; + unsigned int i; + unsigned int j; + + if (!s1 || !s2) + return (NULL); + tmp = ft_calloc(ft_strlen(s1) + ft_strlen(s2) + 1, sizeof(*tmp)); + if (!tmp) + return (NULL); + i = 0; + while (s1[i]) + { + tmp[i] = s1[i]; + i++; + } + j = 0; + while (s2[j]) + { + tmp[i] = s2[j]; + i++; + j++; + } + tmp[i] = 0; + return (tmp); +} diff --git a/libft/ft_strlcat.c b/libft/ft_strlcat.c new file mode 100644 index 0000000..f89bf09 --- /dev/null +++ b/libft/ft_strlcat.c @@ -0,0 +1,37 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strlcat.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/04 16:10:59 by vvobis #+# #+# */ +/* Updated: 2024/04/10 16:41:14 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +size_t ft_strlcat(char *dest, char const *src, size_t size) +{ + size_t dlen; + size_t slen; + + if (size == 0) + return (ft_strlen(src)); + dlen = ft_strlen(dest); + slen = ft_strlen(src); + if (size <= dlen) + return (slen + size); + if (dlen + slen < size) + { + ft_memcpy(&dest[dlen], src, slen); + dest[dlen + slen] = 0; + } + else + { + ft_memcpy(&dest[dlen], src, size - dlen); + dest[size - 1] = 0; + } + return (dlen + slen); +} diff --git a/libft/ft_strlcpy.c b/libft/ft_strlcpy.c new file mode 100644 index 0000000..b34a653 --- /dev/null +++ b/libft/ft_strlcpy.c @@ -0,0 +1,32 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strlcpy.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/02 19:03:18 by vvobis #+# #+# */ +/* Updated: 2024/04/09 19:28:44 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +size_t ft_strlcpy(char *dest, char const *src, size_t size) +{ + size_t i; + + i = 0; + if (size != 0) + { + while (src[i] != '\0' && i < size - 1) + { + dest[i] = src[i]; + i++; + } + dest[i] = '\0'; + } + while (src[i] != '\0') + i++; + return (i); +} diff --git a/libft/ft_strlen.c b/libft/ft_strlen.c new file mode 100644 index 0000000..863d026 --- /dev/null +++ b/libft/ft_strlen.c @@ -0,0 +1,29 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strlen.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: anarama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/02 16:01:03 by vvobis #+# #+# */ +/* Updated: 2024/07/19 11:22:23 by anarama ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +size_t ft_strlen(char const *str) +{ + size_t i; + + i = 0; + if (!str) + return (0); + while (*str++) + { + i++; + if (i == SIZE_MAX) + break ; + } + return (i); +} diff --git a/libft/ft_strmapi.c b/libft/ft_strmapi.c new file mode 100644 index 0000000..664792b --- /dev/null +++ b/libft/ft_strmapi.c @@ -0,0 +1,33 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strmapi.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/07 17:01:35 by vvobis #+# #+# */ +/* Updated: 2024/04/12 10:13:57 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +char *ft_strmapi(char const *s, char (*f)(unsigned int, char)) +{ + char *tmp; + unsigned int i; + + if (!s || !f) + return (NULL); + tmp = ft_calloc(ft_strlen(s) + 1, sizeof(*tmp)); + if (!tmp) + return (NULL); + i = 0; + while (s[i]) + { + tmp[i] = f(i, s[i]); + i++; + } + tmp[i] = 0; + return (tmp); +} diff --git a/libft/ft_strncmp.c b/libft/ft_strncmp.c new file mode 100644 index 0000000..f42fd81 --- /dev/null +++ b/libft/ft_strncmp.c @@ -0,0 +1,31 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strncmp.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/03 13:33:22 by vvobis #+# #+# */ +/* Updated: 2024/04/12 10:29:59 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +int ft_strncmp(char const *s1, char const *s2, size_t n) +{ + size_t i; + + if (n == 0) + return (0); + i = 0; + while ((s1[i] || s2[i]) && i < n) + { + if (s1[i] < s2[i]) + return ((unsigned char)s1[i] - (unsigned char)s2[i]); + else if (s1[i] > s2[i]) + return ((unsigned char)s1[i] - (unsigned char)s2[i]); + i++; + } + return (0); +} diff --git a/libft/ft_strnstr.c b/libft/ft_strnstr.c new file mode 100644 index 0000000..2733d0e --- /dev/null +++ b/libft/ft_strnstr.c @@ -0,0 +1,36 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strnstr.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/03 15:36:41 by vvobis #+# #+# */ +/* Updated: 2024/04/10 16:42:02 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +char *ft_strnstr(char const *s1, char const *s2, size_t n) +{ + size_t i; + size_t j; + + if (!*s2) + return ((char *)s1); + i = 0; + while (i < n && s1[i]) + { + j = 0; + if (s1[i + j] == s2[j]) + { + while (s1[i + j] == s2[j] && s1[i + j] && i + j < n) + j++; + if (!s2[j]) + return ((char *)&s1[i]); + } + i++; + } + return (NULL); +} diff --git a/libft/ft_strrchr.c b/libft/ft_strrchr.c new file mode 100644 index 0000000..e5d7d65 --- /dev/null +++ b/libft/ft_strrchr.c @@ -0,0 +1,33 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strrchr.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/03 12:20:50 by vvobis #+# #+# */ +/* Updated: 2024/04/09 20:54:22 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +char *ft_strrchr(char const *s, int c) +{ + char *n; + int i; + + i = 0; + n = NULL; + while (s[i] != 0) + { + if (s[i] == (char)c) + n = (char *)&s[i]; + i++; + } + if ((char)c == 0) + return ((char *)&s[i]); + if (n) + return (n); + return (NULL); +} diff --git a/libft/ft_strtrim.c b/libft/ft_strtrim.c new file mode 100644 index 0000000..e02e096 --- /dev/null +++ b/libft/ft_strtrim.c @@ -0,0 +1,47 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strtrim.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/04 19:30:35 by vvobis #+# #+# */ +/* Updated: 2024/04/15 13:07:55 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +static int is_set(char c, char const *s) +{ + while (*s) + if (c == *s++) + return (1); + return (0); +} + +static int find_end(char const *s1, char const *set) +{ + int i; + + i = 0; + while (*s1) + s1++; + while (is_set(*--s1, set)) + i++; + return (i); +} + +char *ft_strtrim(char const *s1, char const *set) +{ + if (!s1) + return (NULL); + if (!set) + return ((char *)s1); + while (is_set(*s1, set) && *s1) + s1++; + if ((int)ft_strlen(s1) > find_end(s1, set)) + return (ft_substr(s1, 0, ft_strlen(s1) - find_end(s1, set))); + else + return (ft_calloc(1, 1)); +} diff --git a/libft/ft_substr.c b/libft/ft_substr.c new file mode 100644 index 0000000..b9e148f --- /dev/null +++ b/libft/ft_substr.c @@ -0,0 +1,41 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_substr.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/04 18:58:25 by vvobis #+# #+# */ +/* Updated: 2024/04/09 21:50:44 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +char *ft_substr(char const *s, unsigned int start, size_t len) +{ + char *tmp; + unsigned int i; + + i = 0; + if (!s || start >= ft_strlen(s) || len <= 0) + { + tmp = malloc(1); + if (!tmp) + return (NULL); + tmp[i] = 0; + return (tmp); + } + if (len + start > ft_strlen(s)) + len = ft_strlen(s) - start; + tmp = malloc(sizeof(*tmp) * len + 1); + if (!tmp) + return (NULL); + while (i < len && s[i]) + { + tmp[i] = s[i + start]; + i++; + } + tmp[i] = 0; + return (tmp); +} diff --git a/libft/ft_tolower.c b/libft/ft_tolower.c new file mode 100644 index 0000000..d7c4540 --- /dev/null +++ b/libft/ft_tolower.c @@ -0,0 +1,20 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_tolower.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/03 12:01:54 by vvobis #+# #+# */ +/* Updated: 2024/04/03 12:15:18 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +int ft_tolower(int c) +{ + if (c >= 65 && c <= 90) + c += 32; + return (c); +} diff --git a/libft/ft_toupper.c b/libft/ft_toupper.c new file mode 100644 index 0000000..7bcb06a --- /dev/null +++ b/libft/ft_toupper.c @@ -0,0 +1,20 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_toupper.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/03 12:18:44 by vvobis #+# #+# */ +/* Updated: 2024/04/03 12:19:05 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +int ft_toupper(int c) +{ + if (c >= 97 && c <= 122) + c -= 32; + return (c); +} diff --git a/libft/get_next_line.c b/libft/get_next_line.c new file mode 100644 index 0000000..eb9dad2 --- /dev/null +++ b/libft/get_next_line.c @@ -0,0 +1,109 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* get_next_line.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/18 20:20:17 by vvobis #+# #+# */ +/* Updated: 2024/06/14 00:05:31 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "get_next_line.h" + +void *buffer_extend(void *ptr_old, size_t size_new, size_t size_old) +{ + void *ptr_new; + void *ptr_back; + void *ptr_old_free; + + ptr_new = g_calloc(size_new + 1, 1); + if (!ptr_new) + return (free(ptr_old), ptr_old = NULL, NULL); + ptr_back = ptr_new; + ptr_old_free = ptr_old; + while (size_old--) + *(char *)ptr_new++ = *(char *)ptr_old++; + return (free(ptr_old_free), ptr_old_free = NULL, ptr_back); +} + +char *handle_no_nl(char **buf, char **left) +{ + if (left) + { + free(*left); + *left = NULL; + } + if (!buf) + return (NULL); + if (g_strlen(*buf)) + return (*buf); + free(*buf); + *buf = NULL; + return (NULL); +} + +char *line_extract(char **buf_joined, char **left, size_t line_len) +{ + char *line; + + line = g_substr(*buf_joined, 0, line_len); + if (!line) + return (free(*buf_joined), *buf_joined = NULL, (char *)-1); + *left = g_substr(*buf_joined, line_len, g_strlen(*buf_joined) - line_len); + free(*buf_joined); + *buf_joined = NULL; + if (!*left) + return (free(line), line = NULL, (char *)-1); + return (line); +} + +char *line_handle(char **buf_fetch) +{ + char *buf_joined; + size_t line_len; + static char *left; + + if (!buf_fetch) + return (free(left), left = NULL, (char *)-1); + buf_joined = g_strjoin(left, *buf_fetch); + free(*buf_fetch); + *buf_fetch = NULL; + free(left); + left = NULL; + if (!buf_joined) + return ((char *)-1); + line_len = find_newline(buf_joined); + if (line_len) + return (line_extract(&buf_joined, &left, line_len)); + return (handle_no_nl(&buf_joined, &left)); +} + +char *get_next_line(int fd) +{ + char *buf; + ssize_t bytes_read; + size_t buf_size_cur; + size_t buf_size_prev; + + if (fd < 0) + return (line_handle(NULL), NULL); + buf = g_calloc(sizeof(*buf), BUFFER_SIZE + 1); + buf_size_prev = 0; + buf_size_cur = BUFFER_SIZE; + while (1) + { + if (!buf) + return (line_handle(NULL)); + bytes_read = read(fd, buf + buf_size_prev, BUFFER_SIZE); + if (bytes_read < 0) + return (free(buf), buf = NULL, line_handle(NULL)); + if (find_newline(buf) || bytes_read == 0) + break ; + buf_size_prev = buf_size_cur; + buf_size_cur += BUFFER_SIZE; + buf = buffer_extend(buf, buf_size_cur, buf_size_prev); + } + return (line_handle(&buf)); +} diff --git a/libft/get_next_line.h b/libft/get_next_line.h new file mode 100644 index 0000000..60a48d4 --- /dev/null +++ b/libft/get_next_line.h @@ -0,0 +1,38 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* get_next_line.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/15 14:07:36 by vvobis #+# #+# */ +/* Updated: 2024/05/27 17:43:21 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef GET_NEXT_LINE_H + +# define GET_NEXT_LINE_H + +# ifndef BUFFER_SIZE + +# define BUFFER_SIZE 50 + +# endif + +# define MAX_FD 1024 + +# include +# include +# include +# include + +char *get_next_line(int fd); +char *g_strjoin(char const *s1, char const *s2); +size_t g_strlen(char const *str); +void *g_calloc(size_t n, size_t s); +char *g_substr(char const *s, unsigned int start, size_t len); +char *line_handle(char **buf_fetch); +size_t find_newline(char *buf); + +#endif diff --git a/libft/get_next_line_utils.c b/libft/get_next_line_utils.c new file mode 100644 index 0000000..736d5e7 --- /dev/null +++ b/libft/get_next_line_utils.c @@ -0,0 +1,118 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* get_next_line_utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/15 14:14:13 by vvobis #+# #+# */ +/* Updated: 2024/06/13 23:37:48 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "get_next_line.h" + +size_t g_strlen(char const *str) +{ + size_t i; + + if (!str) + return (0); + i = 0; + while (*str) + { + i++; + str++; + } + return (i); +} + +size_t find_newline(char *buf) +{ + size_t i; + + if (!buf) + return (0); + i = 0; + while (*buf) + { + if (*buf == '\n') + return (i + 1); + i++; + buf++; + } + return (0); +} + +char *g_strjoin(char const *s1, char const *s2) +{ + char *tmp; + unsigned int i; + unsigned int j; + + if (!s2) + return (NULL); + if (!s1) + return (g_substr(s2, 0, g_strlen(s2))); + tmp = g_calloc(g_strlen(s1) + g_strlen(s2) + 1, sizeof(*tmp)); + if (!tmp) + return (NULL); + i = 0; + if (s1) + { + while (s1[i]) + { + tmp[i] = s1[i]; + i++; + } + } + j = 0; + if (s2) + while (s2[j]) + tmp[i++] = s2[j++]; + return (tmp); +} + +char *g_substr(char const *s, unsigned int start, size_t len) +{ + char *tmp; + unsigned int i; + + i = 0; + if (!s || start >= g_strlen(s) || len <= 0) + { + tmp = malloc(1); + if (!tmp) + return (NULL); + tmp[i] = 0; + return (tmp); + } + if (len + start > g_strlen(s)) + len = g_strlen(s) - start; + tmp = g_calloc(len + 1, sizeof(*tmp)); + if (!tmp) + return (NULL); + while (i < len && s[i]) + { + tmp[i] = s[i + start]; + i++; + } + return (tmp); +} + +void *g_calloc(size_t n, size_t s) +{ + char *tmp; + unsigned long i; + + i = 0; + if (n == 0) + return (malloc(0)); + if (SIZE_MAX / n < s) + return (NULL); + tmp = malloc(n * s); + if (tmp) + while (i < n * s) + tmp[i++] = 0; + return ((void *)tmp); +} diff --git a/libft/libft.a b/libft/libft.a new file mode 100644 index 0000000..e5985a1 Binary files /dev/null and b/libft/libft.a differ diff --git a/libft/libft.h b/libft/libft.h new file mode 100644 index 0000000..3accb20 --- /dev/null +++ b/libft/libft.h @@ -0,0 +1,97 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* libft.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/09 23:43:36 by vvobis #+# #+# */ +/* Updated: 2024/08/23 15:52:33 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef LIBFT_H + +# define LIBFT_H + +# include +# include +# include +# include +# include +# include "ft_printf.h" +# include + +typedef struct s_list +{ + void *content; + struct s_list *next; +} t_list; + +/* Input Handeling */ +char ***super_split(char **strs, int size, int delimiter); +void *free_super_split(char ***back); +char *get_next_line(int fd); + +int ft_isalpha(int c); +int ft_isdigit(int c); +int ft_isalnum(int c); +int ft_isprint(int c); +int ft_isascii(int c); +int is_space(char const c); + +/*Memory Management*/ +int ft_memcmp(void *s1, void const *s2, size_t n); +void *ft_memset(void *s, int c, size_t n); +void ft_bzero(void *s, size_t n); +void *ft_memcpy(void *dest, void const *src, size_t n); +void *ft_memmove(void *dest, void const *src, size_t n); +void *ft_memchr(void *s, int c, size_t n); +void *ft_calloc(size_t n, size_t s); + +/*Info Conversion*/ +int ft_atoi(char const *s); +long ft_atol(char const *s, uint8_t *too_big); +char *ft_itoa(int n); +char *ft_ltoa(long long n); +char **ft_split(char const *s, char c); + +/*String Manip*/ +int ft_toupper(int c); +int ft_tolower(int c); +int ft_strncmp(char const *s1, char const *s2, size_t n); +char *ft_strnstr(char const *s1, char const *s2, size_t n); +char *ft_strchr(char const *s, int c); +char *ft_strrchr(char const *s, int c); +char *ft_strdup(char const *s); +char *ft_substr(char const *s, unsigned int start, size_t len); +char *ft_strjoin(char const *s1, char const *s2); +char *ft_strtrim(char const *s1, char const *set); +char *ft_strmapi(char const *s, char (*f)(unsigned int, char)); +void ft_striteri(char const *s, void (*f)(unsigned int, char *)); +size_t ft_strlcpy(char *dest, char const *src, size_t size); +size_t ft_strlcat(char *dest, char const *src, size_t size); +size_t ft_strlen(char const *str); + +/*List manip*/ +int ft_lstsize(t_list *lst); +void ft_lstdelone(t_list *lst, void (*del)(void*)); +void ft_lstclear(t_list **lst, void (*del)(void*)); +void ft_lstiter(t_list *lst, void (*f)(void *)); +void ft_lstadd_front(t_list **lst, t_list *node_new); +void ft_lstadd_back(t_list **lst, t_list *node_new); +t_list *ft_lstmap(t_list *lst, void *(*f)(void *), void (*del)(void *)); +t_list *ft_lstnew(void *content); +t_list *ft_lstlast(t_list *lst); + +/*Output*/ +void ft_putchar_fd(char c, int fd); +void ft_putstr_fd(const char *str, int fd); +void ft_putendl_fd(char *str, int fd); +void ft_putnbr_fd(int n, int fd); + +/* safe functions */ + +void ft_free(void *ptr); + +#endif diff --git a/minishell.h b/minishell.h new file mode 100644 index 0000000..c2eefb8 --- /dev/null +++ b/minishell.h @@ -0,0 +1,581 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* minishell.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: anarama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/07/05 12:16:38 by victor #+# #+# */ +/* Updated: 2024/08/27 17:28:49 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef MINISHELL_H +# define MINISHELL_H + +# include +# include "libft/libft.h" +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include + +# define PWD 0 +# define CUSTOM 1 + +# define PROMPT_COMMAND_STACK_SIZE 16 +# define PROMPT_INPUT_BUFFER_SIZE 4096 +# define CURSOR_MOVE_HOME "\033[H" +# define GREEN "\033[0;32m" +# define RESET "\033[0m" +# define RED "\033[0;31m" +# define CURSOR_MOVE_UP "\033[A" +# define CURSOR_MOVE_DOWN "\033[B" +# define CURSOR_MOVE_RIGHT "\033[C" +# define CURSOR_MOVE_LEFT "\033[D" +# define CURSOR_POSITION_GET "\033[6n" +# define CURSOR_POSITION_SET "\033[%d;%dH" +# define CURSOR_POSITION_SAVE "\033[s" +# define CURSOR_POSITION_RESTORE "\033[u" + +# define MAXIMUM_COLUMN 9999 +# define MAXIMUM_ROW 9999 +# define SCREEN_MAX "\033[9999;9999H" +# define DEL 127 +# define EOT 4 +# define ESC 27 + +# define VARIABLE_TOKEN_SIZE 1024 + +# define SCREEN_DISBLE_WRAPPING "\033[?7l" +# define SCREEN_ENABLE_WRAPPING "\033[?7h" +# define SCREEN_CLEAR_TO_EOL "\033[K" +# define SCREEN_CLEAR "\033[2J" +# define SCREEN_CLEAR_TO_EOF "\033[J" + +# define ENVIRONMENT_SIZE 512 +# define INITIAL_TOKEN_CAPACITY 16 + +# define BUFFER_CAPACITY 64 + +typedef struct s_history_buffer +{ + uint write; + uint read; + uint buffer_capacity; + char *buffer[BUFFER_CAPACITY]; +} t_history_buffer; + +typedef struct s_prompt +{ + bool exists; + char *prompt; + t_history_buffer history; + uint32_t cursor_position[2]; + void (*prompt_display_func)(char *); + uint32_t prompt_length; + char *command; +} t_prompt; + +typedef enum e_token_type +{ + TOKEN_WORD = 1, + TOKEN_REDIRECT_OUT, + TOKEN_REDIRECT_IN, + TOKEN_REDIRECT_APPEND, + TOKEN_HEREDOC, + TOKEN_PIPE, + TOKEN_AND, + TOKEN_OR, + TOKEN_NEWLINE, + TOKEN_SEMICOLON, + TOKEN_EOL, + TOKEN_DONE, +} t_token_type; + +typedef struct s_token +{ + t_token_type token_type; + char *token_value; +} t_token; + +typedef struct s_ring_buffer +{ + uint write; + uint read; + uint buffer_capacity; + t_token *buffer[BUFFER_CAPACITY]; +} t_ring_buffer; + +typedef enum t_node_type +{ + NODE_NONE, + NODE_END = TOKEN_EOL, + NODE_PIPE = 6, + NODE_LOGICAL_AND, + NODE_LOGICAL_OR, + NODE_NEWLINE, + NODE_INVALID, +} t_node_type; + +typedef struct s_ast +{ + t_node_type type; + t_token_type token_type; + char **args; + bool is_heredoc; + char *path_file_in; + char *path_file_out; + bool has_redir_in; + bool has_redir_out; + bool was_pipe; + int32_t pipefd[2]; + int fd_in; + int fd_out; + pid_t cpid; +} t_ast; + +enum e_alloc +{ + ADD, + CLEAN, + END, + FREE, +}; + +typedef struct s_clean +{ + void *content; + void (*clean)(void *del); + struct s_clean *next; +} t_clean; + +extern int32_t volatile g_signal_flag; + +/* Builtins */ +int32_t ft_echo(char **args, int32_t *exit_status); +void ft_cd( const char **environment, \ + const char **args, \ + int32_t *exit_status); +void ft_pwd(const char **env, int32_t *exit_status); +void ft_env(const char **env, int32_t *exit_status); +void ft_unset( char **environment, \ + const char **args, \ + int32_t *exit_status); +void ft_export(const char **args, int32_t *exit_status); +void ft_exit(t_ast *tree, int *exit_status); +void *ft_realloc(void *ptr, int old_size, int new_size); + +/* Commands */ +bool is_buildin( t_ast *node); + +bool buildin_execute( t_ast *node, \ + const char **environment, \ + int *exit_status); + +void command_execute( char const *command_path, \ + char const *argv[], \ + char const **env); + +void m_tokenizer( const char *input, \ + char **env, \ + int *exit_status, \ + int32_t std[2]); + +/* non_interactive */ +int32_t minishell_single_command( char *command, \ + char **environment, \ + int32_t std[2]); + +void *ft_realloc_string( char **string, uint32_t *new_size); +char *check_redir_input(void); + +void setup_environment( const char **environment); + +int setup( uint32_t argc, \ + const char **argv, \ + char **environment, \ + int32_t std[2]); + +/* Handle signal */ +void handle_sigint(int sig); +void setup_signal_handlers(void); + +/* Input */ +void free_split(void *back); +uint32_t get_split_size(const char **split); +uint32_t get_split_length(char **split); +int get_amount_tokens(t_token *tokens); + +/* List Memory */ +void lst_memory(void *mem, void (*del)(void *c), int mode); +int p_stderr(int stderr_fd, const char *error, const char *specifier); + +/* List */ +t_clean *lst_node_new(void *content, void (*del)(void *)); +void lst_node_del(t_clean **lst); +void lst_node_del_clean(t_clean **lst, void *mem); +void lst_list_clean(t_clean **head); +int lst_add_back(t_clean **node, t_clean *node_new); + +/* Path Utils */ +char *find_absolute_path( const char *path_variable, \ + char *input, \ + int *exit_status); + +/* Prompt */ +void prompt_destroy(void *prompt); +t_prompt prompt_create(uint8_t mode); +char *prompt_get(const char *prompt); + +uint32_t prompt_display_string_set( t_prompt *prompt, \ + const char **environment, \ + const char *prompt_string); + +void handle_arrow_key_up( t_history_buffer *history, \ + char **input, \ + uint32_t cursor_position_current[2]); + +/* Prompt_print.c */ +void prompt_print_custom_string(char *string); +void prompt_print_pwd(char *prompt); + +/* Lexer */ +void evaluate_input( char **input[], \ + int32_t *exit_status, \ + bool *error_caught); + +uint32_t get_spaces(char *input); +uint32_t determine_variables(char **input); +void split_string_by_space(char *to_split, char **input_new); +void adjust_input(char **input, char *new_string); +uint32_t determine_full_length(char *string, char **environment); + +uint32_t evaluate_variable( char ***input, \ + int32_t *exit_status); + +/* input skip pattern */ +bool is_delimiter_variable(char c); +char skip_to_delimiter(char *input_new); +bool skip_single_quotes( char *input, \ + uint32_t *i, \ + bool *in_double_quotes); +bool evaluate_double_quotes(char *input, uint32_t *i); +bool evaluate_single_quotes(char *input, uint32_t *i); + +/* Cursor Manipulation */ +void cursor_position_get(uint32_t cursor_position[2]); +void cursor_position_save(void); +void cursor_position_restore(void); + +bool handle_escape_sequence( t_prompt *prompt, \ + char buffer[], \ + char **input, \ + uint32_t cursor_position[2]); + +char *prompt_get_input( t_prompt *prompt, \ + uint32_t prompt_initial_size, \ + const char *delimiter); + +bool handle_multiple_character( char **input, \ + char buffer[], \ + uint32_t cursor_position[2], \ + uint32_t prompt_length); + +/* Prompt Buffer Management */ +void prompt_refresh_line( char *input, \ + uint32_t cursor_position_base, \ + uint32_t cursor_position[2]); + +char *prompt_buffer_size_manage( char **input, \ + uint32_t old_size, \ + uint32_t size_to_add, \ + uint32_t scalar); + +void prompt_string_insert( char *string_to_insert, \ + char **current_input, \ + char *position_to_insert, \ + uint32_t current_word_length); + +bool handle_new_character_to_input( char **input, \ + char character, \ + uint32_t *cursor_position, \ + uint32_t prompt_length); + +uint8_t handle_single_char_input( char **input, char buffer[], \ + uint32_t cursor_position[2], \ + bool *do_refresh); + +uint8_t handle_single_char_input( char **input, char buffer[], \ + uint32_t cursor_position[2], \ + bool *do_refresh); + +bool handle_new_character_to_input( char **input, \ + char character, \ + uint32_t *cursor_position, \ + uint32_t prompt_length); + +/* Non Blocking mode */ +void blocking_mode_toggle(int flag); + +/* Tab Completion */ +void handle_tab( char **input, t_prompt *prompt); + +void handle_tab_no_match( const char *input_path, \ + char **env, \ + uint32_t cursor_position_current[2], \ + t_prompt *prompt); + +void handle_tab_yes_match( t_prompt *prompt, \ + const char *next_word_match, \ + char **input, \ + uint32_t current_word_length); + +char *determine_word( char *input, \ + char **input_path, \ + uint32_t cursor_position_current); + +void get_next_word_match( char **input, \ + t_prompt *prompt, \ + char *input_path, \ + bool *is_directory); + +void handle_rapid_input( char buffer[], \ + uint32_t cursor_position[2], \ + char **input, \ + uint32_t cursor_position_base); + +void handle_backspace( char *input, \ + uint32_t *cursor_position_current, \ + uint32_t input_length_current); + +/* Termios */ +void terminal_raw_mode_enable(int flag); +void terminal_raw_mode_disable(int flag); + +/* Utils */ +int ft_close(int fd, const char *specifier); +void ft_pipe(int pipefd[2], const char *specifier); +void ft_dup2(int fd_old, int fd_new, const char *specifier); +void ft_fork(pid_t *pid, const char *specifier); +void ft_open(int *fd, const char *path, int flag, int mode); +int64_t ft_read(int fd, char *character, uint32_t size_read); +void ft_opendir(DIR **directory, const char *directory_path); +void close_fds(void *std_ptr); + +/* Wildcards */ +void check_and_expand_wildcards(char ***input); +int check_wildcard(char *str); +int get_tokens_count(char **tokens); + +/* Wildcards Helper */ +int compare_suffix( const char *current_position_in_str, \ + const char *current_position_in_pattern); + +int handle_prefix( const char *pattern, \ + const char *str, \ + char *adr_next_wild); + +int handle_middle( const char *pattern, const char *str); + +char **expand_wildcard( const char *pattern); + +/* Environment_variable */ + +void environment_variable_print( const char *variable, \ + const char **environment); + +void environment_print( const char **environment); + +char **environment_create( const char **env); + +void environment_variable_remove( char **environment, \ + const char *variable); + +void environment_variable_add( char ***environment, \ + const char *variable_name, \ + const char *variable_value); + +char **environment_variable_get( const char *variable, \ + const char **environment); + +char *environment_variable_value_get( const char *variable, \ + const char **environment); + +void environment_variable_value_change( const char **environment, \ + const char *variable_name, \ + const char *variable_value); +char **env_static(char **environment); + +/*check_special_symbol.c*/ +int is_special_char(char c); +int ft_isspace(char c); +bool is_in_alphabet(char c); +bool unrecognized_input(char c); + +/*create_token_double_special_symbol.c*/ +int is_double_special(const char *input); +t_token create_token_double_special_symbol(char **input); +bool is_mutliple_lines(char *c); +void remove_qoutes_delimiter(char *delimiter, uint32_t *length); +void token_heredoc_get( t_token *token, const char *delimiter); + +/* token_heredoc.c */ +char *heredoc_while_tokenizing(char *input); +char *handle_delimiter(char *input, char **temp_move); +char *heredoc_loop( char *input, \ + char *temp_move, \ + const char *delimiter, \ + uint32_t delimiter_length); + +/* handle_heredoc.c */ +void handle_heredoc(t_token tokens, int32_t fd); +bool heredoc_has_been_done(t_token *token, char *value, int fd); +void print_value(char *value, int fd); +void remove_quotes(char *s); + +/*create_token_single_special_symbol.c*/ +int is_single_special(const char input); +t_token create_token_single_special_symbol(const char **input); + +/*create_token_word.c*/ +t_token create_token_word(const char **input); + +/*create_token.c*/ +t_token create_token(t_token_type token_type, const char *value); + +/*env_utils.c*/ +void print_tokens(t_token *tokens); + +/* subshell.c */ +char *execute_subshell(char *input, const char **environement); + +/*tokenizer.c*/ +t_token *lexical_analysis(char *input); + +/* tokenizer_heredoc_helper.c */ +void ring_buffer_put( t_ring_buffer *buffer, t_token *entry); + +t_token *ring_buffer_get( t_ring_buffer *buffer); + +t_token mark_tokens_till_heredoc( char *value, char **input); + +void tokenizing_loop( char **input, \ + t_token *tokens, \ + uint32_t *i, \ + t_ring_buffer *heredoc_buffer); + +/*ats_print.c*/ +void print_ast(t_ast *head); + +/*handle_command.c*/ + +void handle_command( t_ast *current, \ + const char **env, \ + int *exit_status, \ + int std[2]); + +void execute_commands( t_ast *tree, \ + const char **env, \ + int *exit_status, \ + int32_t std[2]); + +void wait_pids( t_ast *tree, \ + uint pid_count, \ + pid_t pid_final, \ + int32_t *exit_status); + +/*handle_fds.c*/ +bool handle_fds_child_proccess(t_ast *command, int32_t *exit_status); +void handle_fds_parent_proccess(t_ast *command, int32_t *exit_status); +void handle_pipe_in_child(t_ast *command); +void handle_pipe_in_parent(t_ast *command); +bool buildin_apply_pipe(t_ast *node, int32_t *exit_status); + +/*handle_logical_operator.c*/ +void handle_logical_operator(t_ast **logical_node, int exit_status); + +/* handle_pipes.c */ +void handle_pipe(t_ast *pipe_node, int *error_catched); + +/*handle_redirs.c*/ +void handle_redir_in( t_ast *branch, \ + t_token *token, \ + t_token *token_next); + +void handle_redir_out( t_ast *branch, \ + t_token *token, \ + t_token *token_next); + +void handle_redir_append( t_ast *branch, \ + t_token *token, \ + t_token *token_next); + +void handle_redir_heredoc( t_ast *branch, \ + t_token *token, \ + uint8_t token_id); + +/*parse_tokens.c*/ +t_ast *parse_tokens( t_token *tokens, \ + int32_t *exit_status); +uint32_t determine_trees(t_token *tokens); +void tree_destroy(void *tree_ptr); + +/* Syntac_check.c */ +void check_valid_logical_operator( t_token *token, \ + int index, \ + int *error_catched); + +void check_valid_pipe( t_token *token, \ + int index, \ + int *error_catched); + +void check_valid_redir( t_token *token, \ + int index, \ + int *error_catched); + +void print_error_redir( t_token_type token_type); + +void print_error_logical_operator( t_token_type token_type); + +void restore_fd(int std[2]); + +/*parser.c*/ +void fill_args( char ***args, \ + int count, \ + char *token_value, \ + int *capacity); +bool is_delimiter_token(t_token *token); + +/*syntax_check.c*/ +void check_valid_redir( t_token *token, \ + int index, \ + int *error_catched); + +void check_valid_pipe( t_token *token, \ + int index, \ + int *error_catched); + +void check_valid_logical_operator( t_token *token, \ + int index, \ + int *error_catched); + +void check_valid_heredoc(t_token *token, int index, int *error_catched); + +/* syntax_check_helper.c */ +void print_error_logical_operator(t_token_type token_type); +void print_error_pipe(void); +void print_error_redir(t_token_type token_type); + +void free_tokens(void *token_ptr); +#endif diff --git a/prompt/arrowkeys.c b/prompt/arrowkeys.c new file mode 100644 index 0000000..bdfcd3e --- /dev/null +++ b/prompt/arrowkeys.c @@ -0,0 +1,84 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* arrowkeys.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: anarama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/07/08 11:02:39 by victor #+# #+# */ +/* Updated: 2024/08/26 18:22:57 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" +#include + +void handle_arrow_key_up( t_history_buffer *history, + char **input, + uint32_t cursor_position_current[2]) +{ + if (cursor_position_current[0] > 0) + ft_putstr_fd(CURSOR_MOVE_UP, 1); + if (history->read == 0) + history->read = history->buffer_capacity - 1; + else + history->read -= 1; + if (history->buffer[history->read] == 0) + { + history->read = (history->read + 1) % history->buffer_capacity; + return ; + } + if (history->buffer[history->write] == 0) + history->buffer[history->write] = *input; + *input = history->buffer[history->read]; + cursor_position_current[1] = ft_strlen(*input); +} + +static void handle_arrow_key_down( t_history_buffer *history, + uint32_t cursor_position[2], + char **input) +{ + if (history->read == history->write) + return ; + history->read = (history->read + 1) % history->buffer_capacity; + *input = history->buffer[history->read]; + cursor_position[1] = ft_strlen(*input); +} + +static void handle_arrow_key_right( uint32_t *cursor_position_current, + uint32_t prompt_length_current) +{ + if (cursor_position_current[1] < prompt_length_current) + cursor_position_current[1]++; + else + ft_putstr_fd(CURSOR_MOVE_LEFT, 1); +} + +static void handle_arrow_key_left( uint32_t *cursor_position_current) +{ + if (cursor_position_current[1] > 0) + cursor_position_current[1]--; + else + ft_putstr_fd(CURSOR_MOVE_RIGHT, 1); +} + +bool handle_escape_sequence( t_prompt *prompt, + char buffer[], + char **input, + uint32_t cursor_position_current[2]) +{ + uint32_t prompt_length_current; + + prompt_length_current = ft_strlen(*input); + if (buffer[0] == 91 && buffer[1] == 65) + return (handle_arrow_key_up(&prompt->history, \ + input, cursor_position_current), 1); + else if (buffer[0] == 91 && buffer[1] == 66) + return (handle_arrow_key_down(&prompt->history, \ + cursor_position_current, input), 1); + else if (buffer[0] == 91 && buffer[1] == 67) + handle_arrow_key_right(cursor_position_current, prompt_length_current); + else if (buffer[0] == 91 && buffer[1] == 68) + handle_arrow_key_left(cursor_position_current); + return (0); +} diff --git a/prompt/escape_sequences.c b/prompt/escape_sequences.c new file mode 100644 index 0000000..a33719a --- /dev/null +++ b/prompt/escape_sequences.c @@ -0,0 +1,40 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* escape_sequences.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: anarama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/07/07 19:29:29 by vvobis #+# #+# */ +/* Updated: 2024/08/26 17:05:22 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +void cursor_position_get(uint32_t cursor_position[2]) +{ + char cursor_position_str[32]; + char *cursor_position_str_ptr; + char *cursor_position_str_ptr2; + int bytes_read; + + ft_bzero(&cursor_position_str, 32); + write(1, CURSOR_POSITION_GET, ft_strlen(CURSOR_POSITION_GET)); + bytes_read = read(1, cursor_position_str, 32); + if (bytes_read == -1) + return (perror("read")); + cursor_position_str_ptr = cursor_position_str; + cursor_position_str_ptr2 = ft_strchr(cursor_position_str, ';'); + if (!cursor_position_str_ptr2) + return ; + *cursor_position_str_ptr2 = 0; + while (!(*cursor_position_str_ptr >= '0' + && *cursor_position_str_ptr <= '9')) + cursor_position_str_ptr++; + cursor_position[0] = ft_atoi(cursor_position_str_ptr); + cursor_position_str_ptr = cursor_position_str_ptr2 + 1; + cursor_position_str_ptr2 = ft_strchr(cursor_position_str_ptr, 'R'); + *cursor_position_str_ptr2 = 0; + cursor_position[1] = ft_atoi(cursor_position_str_ptr); +} diff --git a/prompt/non_blocking_mode.c b/prompt/non_blocking_mode.c new file mode 100644 index 0000000..3dab8aa --- /dev/null +++ b/prompt/non_blocking_mode.c @@ -0,0 +1,22 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* non_blocking_mode.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/02 17:14:46 by vvobis #+# #+# */ +/* Updated: 2024/08/02 17:16:33 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +void blocking_mode_toggle(int flag) +{ + if (ioctl(0, FIONBIO, &flag) == -1) + { + perror("ioctl"); + exit(1); + } +} diff --git a/prompt/prompt_handle_chars.c b/prompt/prompt_handle_chars.c new file mode 100644 index 0000000..5117f8b --- /dev/null +++ b/prompt/prompt_handle_chars.c @@ -0,0 +1,133 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* prompt_handle_chars.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/02 17:11:28 by vvobis #+# #+# */ +/* Updated: 2024/08/24 12:55:44 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +uint8_t handle_single_char_input( char **input, char buffer[], \ + uint32_t cursor_position_current[2], \ + bool *do_refresh) +{ + uint32_t input_length_current; + uint32_t new_buffer_length; + + input_length_current = ft_strlen(*input); + new_buffer_length = ft_strlen(buffer); + if (new_buffer_length == 1) + { + if (ft_isprint(buffer[0]) || buffer[0] == '\n') + return (*do_refresh = \ + handle_new_character_to_input(input, buffer[0], \ + cursor_position_current, input_length_current), 1); + else if (buffer[0] == EOT \ + && (input_length_current == 0 \ + || (*input)[input_length_current - 1] == '\n')) + return (ft_putstr_fd("\n", 1), \ + terminal_raw_mode_disable(ECHOCTL), \ + g_signal_flag = 2, 1); + } + else + { + *do_refresh = handle_multiple_character(input, buffer, \ + cursor_position_current, input_length_current); + return (1); + } + return (0); +} + +bool handle_new_character_to_input( char **input, + char character, + uint32_t *cursor_position_current, + uint32_t prompt_length_current) +{ + bool do_refresh; + + do_refresh = false; + *input = prompt_buffer_size_manage(input, \ + prompt_length_current, \ + prompt_length_current + 1, \ + PROMPT_INPUT_BUFFER_SIZE); + if (cursor_position_current[1] < prompt_length_current) + { + ft_memmove(&(*input)[cursor_position_current[1] + 1], \ + &(*input)[cursor_position_current[1]], \ + prompt_length_current - cursor_position_current[1]); + do_refresh = true; + } + (*input)[cursor_position_current[1]] = character; + cursor_position_current[1]++; + return (do_refresh); +} + +bool handle_multiple_character( char **input, + char buffer[], + uint32_t cursor_position_current[2], + uint32_t prompt_length_current) +{ + bool do_refresh; + uint32_t buffer_length; + + do_refresh = false; + buffer_length = ft_strlen(buffer); + prompt_buffer_size_manage(input, \ + prompt_length_current, \ + prompt_length_current \ + + buffer_length + 1, \ + PROMPT_INPUT_BUFFER_SIZE); + if (cursor_position_current[1] < prompt_length_current - 1) + { + ft_memmove(&(*input)[cursor_position_current[1] + buffer_length], \ + &(*input)[cursor_position_current[1]], \ + prompt_length_current - cursor_position_current[1] \ + + buffer_length); + do_refresh = true; + } + ft_memcpy(&(*input)[cursor_position_current[1]], buffer, buffer_length); + (cursor_position_current[1]) += buffer_length; + return (do_refresh); +} + +void handle_backspace( char *input, + uint32_t *cursor_position_current, + uint32_t input_length_current) +{ + if (cursor_position_current[1] <= 0) + return ; + cursor_position_current[1]--; + ft_memmove(&input[cursor_position_current[1]], \ + &input[cursor_position_current[1] + 1], \ + input_length_current - cursor_position_current[1]); + ft_putstr_fd(CURSOR_MOVE_LEFT, 1); +} + +void handle_rapid_input( char buffer[], \ + uint32_t cursor_position[2], \ + char **input, \ + uint32_t cursor_position_base) +{ + int32_t bytes_read; + bool do_refresh; + + blocking_mode_toggle(1); + bytes_read = 1; + do_refresh = true; + while (bytes_read > 0) + { + handle_multiple_character(input, buffer, \ + cursor_position, \ + ft_strlen(*input)); + ft_bzero(buffer, 100); + bytes_read = ft_read(0, buffer, 99); + } + blocking_mode_toggle(0); + if (do_refresh) + prompt_refresh_line(*input, cursor_position_base, cursor_position); +} diff --git a/prompt/prompt_input.c b/prompt/prompt_input.c new file mode 100644 index 0000000..db98290 --- /dev/null +++ b/prompt/prompt_input.c @@ -0,0 +1,128 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* prompt_input.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: anarama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/07/07 19:40:20 by vvobis #+# #+# */ +/* Updated: 2024/08/27 17:38:01 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" +#include +#include + +static void handle_accepted_input( t_prompt *prompt, \ + uint32_t cursor_position[2], \ + char **input, \ + char buffer[]) +{ + bool do_refresh; + + do_refresh = true; + if (buffer[0] == ESC) + do_refresh = handle_escape_sequence(prompt, &buffer[1], \ + input, cursor_position); + else if (buffer[0] == '\t') + handle_tab(input, prompt); + else if (buffer[0] == DEL) + handle_backspace(*input, cursor_position, \ + ft_strlen(*input)); + else if (buffer[0] == '\n') + { + handle_new_character_to_input(input, buffer[0], cursor_position, \ + ft_strlen(*input)); + prompt->prompt_display_func(prompt->prompt); + cursor_position[0]++; + return ; + } + else + handle_single_char_input(input, buffer, cursor_position, &do_refresh); + if (do_refresh == true && g_signal_flag != 2) + prompt_refresh_line(*input, prompt->prompt_length, cursor_position); +} + +static bool is_delimiter(char *input, const char *delimiter) +{ + char *tmp; + uint32_t delimiter_length; + + if (*delimiter == '\n') + return (true); + delimiter_length = ft_strlen(delimiter); + tmp = ft_strrchr(input - (*input == '\n' && ft_strlen(input) > 0), '\n'); + if (tmp) + if (tmp++ && ((*tmp == *delimiter && delimiter_length == 1) \ + || ft_strncmp(tmp, delimiter, delimiter_length) == 0)) + return (*tmp = 0, true); + if ((*input == *delimiter && delimiter_length == 1) \ + || ft_strncmp(input, delimiter, delimiter_length) == 0) + return (*input = 0, true); + return (false); +} + +static char *handle_input( t_prompt *prompt, \ + char *input, \ + uint32_t cursor_position[2], \ + const char *delimiter) +{ + char buffer[100]; + int64_t bytes_read; + + while (1) + { + ft_bzero(buffer, 100); + bytes_read = ft_read(0, buffer, 20); + if (g_signal_flag == 1) + return (ft_putstr_fd("^C\n", 1), NULL); + if (bytes_read > 3) + handle_rapid_input(buffer, cursor_position, &input, \ + prompt->prompt_length); + else if (bytes_read >= 1) + { + bytes_read = ft_strlen(buffer); + if (buffer[bytes_read - (bytes_read > 0)] == '\n') + if (is_delimiter(input, delimiter)) + break ; + handle_accepted_input(prompt, cursor_position, &input, buffer); + } + if (g_signal_flag == 2) + return (NULL); + } + return (input); +} + +static void prompt_handle_history(t_history_buffer *buffer, char *input) +{ + buffer->buffer[buffer->write++] = input; + buffer->write %= buffer->buffer_capacity; + buffer->buffer[buffer->write] = 0; + buffer->read = buffer->write; +} + +char *prompt_get_input( t_prompt *prompt, \ + uint32_t prompt_initial_size, \ + const char *delimiter) +{ + char *input; + + input = ft_calloc(prompt_initial_size, sizeof(*input)); + if (!input) + return (perror("malloc"), NULL); + lst_memory(input, free, ADD); + terminal_raw_mode_enable(ECHOCTL | ICANON); + prompt->prompt_display_func(prompt->prompt); + cursor_position_get(prompt->cursor_position); + prompt->cursor_position[1] = 0; + if (!delimiter) + delimiter = "\n"; + input = handle_input(prompt, input, prompt->cursor_position, delimiter); + prompt_handle_history(&prompt->history, input); + terminal_raw_mode_disable(ECHO | ECHOCTL | ICANON); + if (!input) + return (NULL); + prompt->command = input; + return (input); +} diff --git a/prompt/prompt_print.c b/prompt/prompt_print.c new file mode 100644 index 0000000..15c803d --- /dev/null +++ b/prompt/prompt_print.c @@ -0,0 +1,25 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* prompt_print.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/02 16:11:25 by vvobis #+# #+# */ +/* Updated: 2024/08/02 16:12:18 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +void prompt_print_pwd(char *prompt) +{ + ft_putstr_fd(GREEN, 1); + ft_printf("[%s]$ ", prompt); + ft_putstr_fd(RESET, 1); +} + +void prompt_print_custom_string(char *string) +{ + ft_putstr_fd(string, 1); +} diff --git a/prompt/prompt_string_management.c b/prompt/prompt_string_management.c new file mode 100644 index 0000000..edf3deb --- /dev/null +++ b/prompt/prompt_string_management.c @@ -0,0 +1,72 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* prompt_string_management.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: anarama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/07/09 08:16:45 by victor #+# #+# */ +/* Updated: 2025/02/15 15:00:14 by victor ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" +#include +#include + +void cursor_position_save(void) +{ + ft_putstr_fd(CURSOR_POSITION_SAVE, 1); +} + +void cursor_position_restore(void) +{ + ft_putstr_fd(CURSOR_POSITION_RESTORE, 1); +} + +void cursor_position_set(uint32_t row, uint32_t column) +{ + ft_printf(CURSOR_POSITION_SET, row, column); +} + +void prompt_refresh_line(char *input, \ + uint32_t cursor_position_base, \ + uint32_t cursor_position_current[2]) +{ + uint32_t cursor_position_store; + + cursor_position_store = cursor_position_current[1]; + cursor_position_set(cursor_position_current[0], cursor_position_base); + ft_putstr_fd(SCREEN_CLEAR_TO_EOL, 1); + ft_putstr_fd(input, 1); + cursor_position_set(cursor_position_current[0], \ + cursor_position_current[1] + cursor_position_base); + cursor_position_current[1] = cursor_position_store; +} + +char *prompt_buffer_size_manage( char **input, \ + uint32_t old_size, \ + uint32_t size_to_add, \ + uint32_t scalar) +{ + char *input_free_ptr; + uint32_t new_size; + + if (scalar == 0) + return (*input); + if ((old_size + size_to_add) > \ + (scalar * \ + ((old_size / scalar) + 1))) + { + new_size = old_size + size_to_add; + new_size += new_size % scalar; + input_free_ptr = *input; + *input = ft_calloc(1, new_size + 1); + if (!*input) + return (perror("malloc"), lst_memory(NULL, NULL, CLEAN), NULL); + ft_memcpy(*input, input_free_ptr, old_size); + lst_memory(input_free_ptr, NULL, FREE); + lst_memory(*input, free, ADD); + } + return (*input); +} diff --git a/prompt/prompt_utils.c b/prompt/prompt_utils.c new file mode 100644 index 0000000..d156ab7 --- /dev/null +++ b/prompt/prompt_utils.c @@ -0,0 +1,81 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* prompt_utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: anarama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/07/07 19:23:40 by anarama #+# #+# */ +/* Updated: 2024/08/26 17:47:31 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +void prompt_destroy(void *prompt) +{ + t_prompt *prompt_ptr; + + prompt_ptr = (t_prompt *)prompt; + ft_free(&prompt_ptr); +} + +uint32_t prompt_display_string_set( t_prompt *prompt, \ + const char **environment, \ + const char *prompt_string) +{ + char *pwd; + uint32_t prompt_string_length; + + if (!prompt_string) + { + pwd = environment_variable_value_get("PWD", environment); + prompt_string_length = ft_strlen(pwd) + 5; + prompt->prompt = pwd; + } + else + { + prompt_string_length = ft_strlen(prompt_string) + 1; + prompt->prompt = (char *)prompt_string; + } + return (prompt_string_length); +} + +char *prompt_get(const char *prompt) +{ + char *input; + char **environment; + static t_prompt _prompt = {0}; + + environment = env_static(NULL); + if (!_prompt.exists) + _prompt = prompt_create(PWD); + _prompt.prompt = NULL; + _prompt.prompt_length = prompt_display_string_set(&_prompt, \ + (const char **)environment, \ + prompt); + prompt_get_input(&_prompt, PROMPT_INPUT_BUFFER_SIZE, "\n"); + if (!_prompt.command || !*_prompt.command) + return (NULL); + ft_putstr_fd(SCREEN_CLEAR_TO_EOF, 1); + input = ft_strdup(_prompt.command); + if (!input) + return (perror("malloc"), lst_memory(NULL, NULL, CLEAN), NULL); + lst_memory(input, free, ADD); + return (input); +} + +t_prompt prompt_create(uint8_t mode) +{ + t_prompt tmp; + + tmp = (t_prompt){0}; + tmp.history = (t_history_buffer){0}; + tmp.history.buffer_capacity = BUFFER_CAPACITY; + tmp.exists = true; + if (mode == PWD) + tmp.prompt_display_func = prompt_print_pwd; + else if (mode == CUSTOM) + tmp.prompt_display_func = prompt_print_custom_string; + return (tmp); +} diff --git a/prompt/tab_completion.c b/prompt/tab_completion.c new file mode 100644 index 0000000..1f37421 --- /dev/null +++ b/prompt/tab_completion.c @@ -0,0 +1,118 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* tab_completion.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: anarama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/07/08 14:53:58 by victor #+# #+# */ +/* Updated: 2025/02/15 22:23:43 by victor ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" +#include + +void handle_tab_no_match(const char *input_path, \ + char **env, \ + uint32_t cursor_position_current[2], \ + t_prompt *prompt) +{ + struct winsize win; + + ioctl(STDOUT_FILENO, TIOCGWINSZ, &win); + cursor_position_save(); + ft_putstr_fd(SCREEN_CLEAR_TO_EOF, 0); + ft_putstr_fd("\n\r", 1); + command_execute("/bin/ls", \ + (const char *[]){"ls", input_path, NULL}, \ + (const char **)env); + cursor_position_restore(); + if (cursor_position_current[0] == win.ws_row) + prompt->prompt_display_func(prompt->prompt); +} + +void handle_tab_yes_match( t_prompt *prompt, \ + const char *next_word_match, \ + char **input, \ + uint32_t current_word_length) +{ + struct winsize win; + + ioctl(STDOUT_FILENO, TIOCGWINSZ, &win); + handle_multiple_character(input, \ + (char *)(next_word_match + current_word_length), \ + prompt->cursor_position, ft_strlen(*input)); + cursor_position_save(); + ft_putstr_fd("\n\r", 1); + ft_putstr_fd(SCREEN_CLEAR_TO_EOF, 0); + cursor_position_restore(); + if (prompt->cursor_position[0] == win.ws_row) + prompt->prompt_display_func(prompt->prompt); +} + +char *determine_word(char *input, \ + char **input_path, \ + uint32_t cursor_position_current) +{ + char *current_word; + char *current_word_path_end; + char *tmp; + uint32_t i; + + i = cursor_position_current - (cursor_position_current > 0); + current_word_path_end = NULL; + while (i > 0 && input[i] != ' ') + i--; + current_word = &input[i + (i > 0)]; + tmp = ft_strchr(current_word, '/'); + while (tmp) + { + current_word_path_end = tmp; + tmp = ft_strchr(tmp + 1, '/'); + } + if (current_word_path_end) + { + *input_path = ft_substr(current_word, 0, \ + current_word_path_end - current_word + 1); + current_word = current_word_path_end + 1; + return (current_word); + } + return (current_word); +} + +uint32_t find_last_matching_char(const char *current_word, \ + const char *next_word_match) +{ + uint32_t i; + char *current_word_without_path; + + if (!next_word_match) + return (0); + current_word_without_path = ft_strrchr(current_word, '/'); + i = 0; + if (current_word_without_path) + while ((current_word_without_path)[i] == next_word_match[i]) + i++; + else + while (current_word[i] == next_word_match[i]) + i++; + return (i); +} + +void handle_tab(char **input, t_prompt *prompt) +{ + char *input_path; + char **environment; + bool is_directory; + + environment = env_static(NULL); + if (!(*input)[(prompt->cursor_position)[1] \ + - ((prompt->cursor_position)[1] > 0)]) + return (handle_tab_no_match(".", environment, \ + prompt->cursor_position, \ + prompt)); + input_path = NULL; + is_directory = false; + get_next_word_match(input, prompt, input_path, &is_directory); +} diff --git a/prompt/tab_get_word.c b/prompt/tab_get_word.c new file mode 100644 index 0000000..c92ac54 --- /dev/null +++ b/prompt/tab_get_word.c @@ -0,0 +1,88 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* tab_get_word.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/02 17:00:19 by vvobis #+# #+# */ +/* Updated: 2024/08/26 18:22:17 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +static char *find_next_match( char *current_word, \ + uint32_t current_word_length, \ + DIR *directory_current, \ + bool *is_directory) +{ + struct dirent *directory_entry; + char *next_word_match; + + *is_directory = false; + next_word_match = NULL; + if (!current_word || !directory_current || !*current_word) + return (NULL); + while (1) + { + directory_entry = readdir(directory_current); + if (directory_entry == NULL) + break ; + if (ft_strncmp(current_word, \ + directory_entry->d_name, \ + current_word_length) == 0) + { + next_word_match = directory_entry->d_name; + if (directory_entry->d_type == DT_DIR) + *is_directory = true; + } + } + return (next_word_match); +} + +uint32_t get_current_word_length(char *word) +{ + char *word_end; + + if (!word) + return (0); + else if (*word == ' ') + return (1); + word_end = ft_strchr(word, ' '); + if (word_end) + return (word_end - word); + return (ft_strlen(word)); +} + +void get_next_word_match( char **input, \ + t_prompt *prompt, \ + char *input_path, \ + bool *is_directory) +{ + DIR *directory_current; + uint32_t current_word_length; + char *next_word_match; + char *current_word; + + current_word = determine_word(*input, &input_path, \ + prompt->cursor_position[1]); + current_word_length = get_current_word_length(current_word); + if (input_path) + directory_current = opendir(input_path); + else + directory_current = opendir("./"); + next_word_match = find_next_match(current_word, current_word_length, \ + directory_current, is_directory); + if (!next_word_match) + handle_tab_no_match(input_path, env_static(NULL), \ + prompt->cursor_position, prompt); + else + handle_tab_yes_match(prompt, next_word_match, input, \ + ft_strlen(current_word)); + if (*is_directory) + handle_new_character_to_input(input, '/', prompt->cursor_position, \ + ft_strlen(*input)); + closedir(directory_current); + ft_free(&input_path); +} diff --git a/src/commands.c b/src/commands.c new file mode 100644 index 0000000..e69ca63 --- /dev/null +++ b/src/commands.c @@ -0,0 +1,74 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* commands.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: anarama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/07/06 21:20:49 by victor #+# #+# */ +/* Updated: 2024/08/27 17:26:44 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +void restore_fd(int std[2]) +{ + ft_dup2(std[0], STDIN_FILENO, "in restore_fd"); + ft_dup2(std[1], STDOUT_FILENO, "in restore_fd"); + ft_close(std[0], "in execution"); + ft_close(std[1], "in execution"); + std[0] = dup(STDIN_FILENO); + std[1] = dup(STDOUT_FILENO); + if (std[0] == -1 || std[1] == -1) + { + perror("dup"); + lst_memory(NULL, NULL, CLEAN); + } +} + +void close_fds(void *std_ptr) +{ + int *std; + + std = std_ptr; + ft_close(STDIN_FILENO, "close fds"); + ft_close(STDOUT_FILENO, "close fds"); + ft_close(STDERR_FILENO, "close fds"); + ft_close(std[0], "close fds"); + ft_close(std[1], "close fds"); +} + +void print_tokens(t_token *tokens) +{ + int i; + + i = 0; + printf("----TOKENS----\n"); + while (tokens[i].token_type != TOKEN_EOL) + { + printf("Token: Type=%d, Value=%s\n", \ + tokens[i].token_type, tokens[i].token_value); + i++; + } + printf("------------\n"); +} + +void m_tokenizer( const char *input, char **env, \ + int *exit_status, int32_t std[2]) +{ + t_token *tokens; + t_ast *tree; + + if (input) + { + tokens = lexical_analysis((char *)input); + if (tokens) + { + tree = parse_tokens(tokens, exit_status); + if (tree) + execute_commands(tree, (const char **)env, exit_status, std); + lst_memory(tokens, NULL, FREE); + } + } +} diff --git a/src/environment_variables.c b/src/environment_variables.c new file mode 100644 index 0000000..d6d5aad --- /dev/null +++ b/src/environment_variables.c @@ -0,0 +1,129 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* environment_variables.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/07/16 11:56:00 by vvobis #+# #+# */ +/* Updated: 2024/08/19 23:06:52 by victor ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" +#include + +void environment_print(const char **environment) +{ + uint32_t i; + + i = 0; + while (environment[i]) + { + ft_putendl_fd((char *)environment[i], 1); + i++; + } +} + +void environment_variable_print( const char *variable, \ + const char **environment) +{ + uint32_t i; + uint64_t variable_length; + char *variable_findable_name; + + if (!variable || !environment) + return ; + i = 0; + variable_length = ft_strlen(variable); + variable_findable_name = ft_calloc(variable_length + 2, sizeof(*variable)); + if (!variable_findable_name) + return (lst_memory(NULL, NULL, CLEAN)); + ft_strlcpy(variable_findable_name, variable, variable_length + 1); + ft_strlcpy(variable_findable_name + variable_length, "=", 2); + variable_length = ft_strlen(variable_findable_name); + while (environment[i]) + { + if (ft_strncmp(variable_findable_name, environment[i], \ + variable_length) == 0) + { + ft_putendl_fd((char *)environment[i] + variable_length, 1); + break ; + } + i++; + } + ft_free((void **)&variable_findable_name); +} + +char *environment_variable_value_get( const char *variable, \ + const char **environment) +{ + uint32_t i; + uint64_t variable_length; + + if (!variable || !environment) + return (NULL); + i = 0; + variable_length = ft_strlen(variable); + while (environment[i]) + { + if (ft_strncmp(variable, environment[i], \ + variable_length) == 0) + if (environment[i][variable_length] == '=') + return ((char *)environment[i] + variable_length + 1); + i++; + } + return (NULL); +} + +char **environment_variable_get( const char *variable, \ + const char **environment) +{ + uint32_t i; + uint64_t variable_length; + char *variable_findable_name; + + if (!variable || !environment) + return (NULL); + i = 0; + variable_length = ft_strlen(variable); + variable_findable_name = ft_calloc(variable_length + 2, sizeof(*variable)); + if (!variable_findable_name) + return (lst_memory(NULL, NULL, CLEAN), NULL); + ft_strlcpy(variable_findable_name, variable, variable_length + 1); + ft_strlcpy(variable_findable_name + variable_length, "=", 2); + variable_length = ft_strlen(variable_findable_name); + while (environment[i]) + { + if (ft_strncmp(variable_findable_name, environment[i], \ + variable_length) == 0) + return (ft_free(&variable_findable_name), (char **)&environment[i]); + i++; + } + ft_free(&variable_findable_name); + return (NULL); +} + +void environment_variable_value_change( const char **environment, \ + const char *variable_name, \ + const char *variable_new_value) +{ + char **variable_to_change; + char *new_variable; + uint32_t new_variable_length; + + variable_to_change = environment_variable_get(variable_name, environment); + if (!variable_to_change) + return ; + new_variable_length = ft_strlen(variable_name) \ + + ft_strlen(variable_new_value) + 2; + new_variable = ft_calloc(new_variable_length, sizeof(*new_variable)); + lst_memory(new_variable, free, ADD); + if (!new_variable) + lst_memory(NULL, NULL, CLEAN); + ft_strlcpy(new_variable, variable_name, ft_strlen(variable_name) + 1); + ft_strlcpy(new_variable + ft_strlen(new_variable), "=", 2); + ft_strlcpy(new_variable + ft_strlen(new_variable), variable_new_value, \ + ft_strlen(variable_new_value) + 1); + *variable_to_change = new_variable; +} diff --git a/src/environment_variables_manip.c b/src/environment_variables_manip.c new file mode 100644 index 0000000..7ad9c86 --- /dev/null +++ b/src/environment_variables_manip.c @@ -0,0 +1,130 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* environment_variables_manip.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/02 17:33:41 by vvobis #+# #+# */ +/* Updated: 2024/08/27 15:12:46 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +static void environment_buffer_extend( char ***environment, \ + uint32_t environment_length_current) +{ + uint32_t environment_size_multiplier; + void *env_ptr; + + environment_size_multiplier = environment_length_current / ENVIRONMENT_SIZE; + if ((ENVIRONMENT_SIZE * (environment_size_multiplier \ + + (environment_size_multiplier < 1))) \ + < environment_length_current) + { + env_ptr = environment; + *environment = environment_create((const char **)env_ptr); + lst_memory(env_ptr, NULL, FREE); + lst_memory(environment, free_split, ADD); + } +} + +char **environment_create(const char **env) +{ + char **environment_new; + char *pwd; + uint32_t i; + + environment_new = ft_calloc(ENVIRONMENT_SIZE + 1, sizeof(*environment_new)); + lst_memory(environment_new, free, ADD); + i = 0; + while (env[i]) + { + environment_new[i] = (char *)env[i]; + i++; + } + pwd = getcwd(NULL, 0); + if (!pwd) + { + perror("getcwd"); + lst_memory(NULL, NULL, CLEAN); + } + environment_variable_value_change((const char **)environment_new, \ + "PWD", pwd); + ft_free(&pwd); + return (environment_new); +} + +void clear_spaces(char *variable) +{ + uint32_t i; + uint32_t j; + + i = 0; + while (variable[i]) + { + j = 0; + if (variable[i] == ' ') + { + while (variable[i + j] && variable[i + j] == ' ') + j++; + ft_memmove(&variable[i + 1], \ + &variable[i + j], ft_strlen(&variable[i])); + } + i++; + } +} + +void environment_variable_add( char ***environment, + const char *variable_new_name, + const char *variable_new_value) +{ + char *variable_to_add; + uint32_t variable_new_name_length; + uint32_t variable_new_value_length; + uint64_t environment_length_current; + + if (environment_variable_get(variable_new_name, \ + (const char **)*environment)) + return (environment_variable_value_change(\ + (const char **)*environment, variable_new_name, variable_new_value)); + environment_length_current = get_split_size((const char **)*environment); + environment_buffer_extend(environment, environment_length_current); + variable_new_name_length = ft_strlen(variable_new_name); + variable_new_value_length = ft_strlen(variable_new_value); + variable_to_add = ft_calloc(variable_new_name_length \ + + variable_new_value_length + 2, \ + sizeof(*variable_to_add)); + lst_memory(variable_to_add, free, ADD); + ft_strlcpy(variable_to_add, variable_new_name, \ + ft_strlen(variable_new_name) + 1); + ft_strlcpy(variable_to_add + variable_new_name_length, "=", 2); + if (variable_new_value) + ft_strlcpy(variable_to_add + variable_new_name_length + 1, \ + variable_new_value, variable_new_value_length + 1); + clear_spaces(variable_to_add); + (*environment)[environment_length_current] = variable_to_add; +} + +void environment_variable_remove(char **environment, const char *variable) +{ + uint32_t i; + uint32_t variable_length; + + i = 0; + variable_length = ft_strlen(variable); + while (environment[i]) + { + if (ft_strncmp(environment[i], (char *)variable, variable_length) == 0) + { + while (environment[i]) + { + environment[i] = environment[i + 1]; + i++; + } + return ; + } + i++; + } +} diff --git a/src/execution.c b/src/execution.c new file mode 100644 index 0000000..00a8a1c --- /dev/null +++ b/src/execution.c @@ -0,0 +1,141 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* execution.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: victor +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/19 22:54:19 by victor #+# #+# */ +/* Updated: 2025/02/15 22:23:29 by victor ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +void command_execute( const char *command_path, + const char **argv, + const char **env) +{ + pid_t child_proccess; + + ft_fork(&child_proccess, command_path); + if (child_proccess == 0) + { + execve(command_path, (char **)argv, (char **)env); + perror("minishell"); + lst_memory(NULL, NULL, CLEAN); + } + else + { + waitpid(child_proccess, NULL, 0); + } +} + +void wait_pids(t_ast *tree, uint pid_count, \ + pid_t pid_final, int32_t *exit_status) +{ + uint i; + int ret_test; + pid_t wait_pid_ret; + + i = 0; + while (i <= pid_count) + { + if (tree[i].cpid != 0) + { + wait_pid_ret = wait(&ret_test); + if (wait_pid_ret == -1 && g_signal_flag == 3) + { + ft_putstr_fd("Quit (core dumped)\n", 1); + continue ; + } + else if (wait_pid_ret == -1 && g_signal_flag == 1) + continue ; + else if (wait_pid_ret == -1) + return (perror("wait"), lst_memory(NULL, NULL, CLEAN)); + if (wait_pid_ret == pid_final) + *exit_status = WEXITSTATUS(ret_test); + tree[i].cpid = 0; + } + i++; + } +} + +static void execution_loop_helper( t_ast *tree, \ + uint32_t *i, \ + int32_t std[2], \ + int32_t *exit_status) +{ + if (tree[*i].type != NODE_PIPE) + { + restore_fd(std); + if (tree[*i].cpid != 0) + wait_pids(tree, *i, tree[*i].cpid, exit_status); + } + else + { + ft_dup2(std[1], STDOUT_FILENO, \ + "in execution_loop execution_loop_helper"); + } + if ((tree[*i].type == NODE_LOGICAL_OR \ + && *exit_status == 0)) + (*i)++; + else if ((tree[*i].type == NODE_LOGICAL_AND \ + && *exit_status != 0)) + (*i)++; +} + +void execution_loop( t_ast *tree, \ + const char **env, \ + int *exit_status, \ + int std[2]) +{ + bool error_found; + + error_found = false; + if (tree->type != NODE_INVALID) + { + if (tree->has_redir_in \ + && tree->path_file_in == 0 \ + && tree->fd_in == -1) + { + return (*exit_status = 1, (void)0); + } + evaluate_input(&tree->args, exit_status, &error_found); + if (tree->args && tree->args[0]) + environment_variable_value_change(env, "_", tree->args[0]); + if (*exit_status == -1 || error_found == true) + return (*exit_status = 2, (void)0); + handle_command(tree, env, exit_status, std); + } +} + +void execute_commands( t_ast *tree, const char **env, \ + int *exit_status, int std[2]) + +{ + uint32_t i; + bool was_pipe; + + i = 0; + if (std[0] == -1 || std[1] == -1) + { + perror("dup"); + lst_memory(NULL, NULL, CLEAN); + } + was_pipe = false; + while (tree[i].type != NODE_END) + { + if (was_pipe == true) + { + tree[i].was_pipe = true; + was_pipe = false; + } + execution_loop(&tree[i], env, exit_status, std); + execution_loop_helper(tree, &i, std, exit_status); + if (tree[i].type == NODE_PIPE) + was_pipe = true; + i++; + } + restore_fd(std); +} diff --git a/src/handle_signals.c b/src/handle_signals.c new file mode 100644 index 0000000..acbbb71 --- /dev/null +++ b/src/handle_signals.c @@ -0,0 +1,39 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* handle_signals.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: anarama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/07/07 14:28:41 by anarama #+# #+# */ +/* Updated: 2025/02/15 22:29:27 by victor ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +void handle_sigint(int sig) +{ + if (sig == SIGINT) + { + g_signal_flag = 1; + } + else if (sig == SIGQUIT) + { + g_signal_flag = 3; + } +} + +void setup_signal_handlers(void) +{ + struct sigaction sa; + + bzero(&sa, sizeof(sa)); + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = handle_sigint; + sigaction(SIGINT, &sa, NULL); + sigaction(SIGQUIT, &sa, NULL); + sa.sa_handler = SIG_IGN; + sigaction(SIGTSTP, &sa, NULL); +} diff --git a/src/input.c b/src/input.c new file mode 100644 index 0000000..22fe819 --- /dev/null +++ b/src/input.c @@ -0,0 +1,71 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* input.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: anarama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/05/14 16:18:42 by vvobis #+# #+# */ +/* Updated: 2024/08/19 22:58:56 by victor ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +void free_split(void *back) +{ + char **free_back; + + if (!back) + return ; + free_back = (char **)back; + while (*free_back) + { + ft_free((void *)free_back); + free_back++; + } + ft_free(&back); + return ; +} + +uint32_t get_split_length(char **split) +{ + uint32_t i; + uint32_t k; + uint32_t j; + + i = 0; + k = 0; + while (split[i]) + { + j = 0; + while (split[i][j++]) + k++; + i++; + } + return (k); +} + +uint32_t get_split_size(const char **split) +{ + uint32_t i; + + i = 0; + if (!split) + return (0); + while (split[i]) + i++; + return (i); +} + +int get_amount_tokens(t_token *tokens) +{ + int i; + + i = 0; + while (tokens[i].token_type != TOKEN_EOL) + { + i++; + } + return (i); +} diff --git a/src/list.c b/src/list.c new file mode 100644 index 0000000..75ab899 --- /dev/null +++ b/src/list.c @@ -0,0 +1,95 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* list.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: anarama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/27 11:44:46 by vvobis #+# #+# */ +/* Updated: 2024/07/30 11:45:03 by victor ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +t_clean *lst_node_new(void *content, void (*del)(void *)) +{ + t_clean *new; + + if (!content || !del) + return (NULL); + new = malloc(sizeof(*new)); + if (!new) + return (NULL); + new->content = content; + new->clean = del; + new->next = NULL; + return (new); +} + +void lst_node_del(t_clean **lst) +{ + (*lst)->clean((*lst)->content); + ft_free(&*lst); +} + +void lst_node_del_clean(t_clean **lst, void *mem) +{ + t_clean *tmp; + t_clean *head; + + if (!lst || !*lst) + return ; + head = *lst; + tmp = *lst; + while ((*lst) && (*lst)->next->content != mem) + (*lst) = (*lst)->next; + if (!*lst) + return ; + tmp = *lst; + if ((*lst)->next && (*lst)->next->next) + { + tmp = (*lst)->next->next; + lst_node_del(&(*lst)->next); + (*lst)->next = tmp; + } + else if ((*lst)->next) + lst_node_del(&(*lst)->next); + else + lst_node_del(lst); + *lst = head; +} + +void lst_list_clean(t_clean **head) +{ + t_clean *tmp; + + while (*head) + { + tmp = (*head)->next; + lst_node_del(head); + *head = tmp; + } + free(*head); +} + +int lst_add_back(t_clean **node, t_clean *new) +{ + t_clean *tmp; + + if (!new) + { + perror("malloc"); + return (0); + } + if (*node) + { + tmp = *node; + while (tmp->next) + tmp = tmp->next; + tmp->next = new; + } + else + *node = new; + return (1); +} diff --git a/src/list_memory.c b/src/list_memory.c new file mode 100644 index 0000000..9cc2542 --- /dev/null +++ b/src/list_memory.c @@ -0,0 +1,55 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* list_memory.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: anarama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/07/05 12:21:13 by victor #+# #+# */ +/* Updated: 2024/08/24 12:44:14 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +void lst_memory(void *mem, void (*del)(void *c), int mode) +{ + static t_clean *list; + t_clean *new; + + if (mode == CLEAN) + return (terminal_raw_mode_disable(ECHOCTL | ICANON), \ + lst_list_clean(&list), exit(EXIT_FAILURE)); + if (mode == END) + return (terminal_raw_mode_disable(ECHOCTL | ICANON), \ + lst_list_clean(&list)); + if (mode == FREE) + return (lst_node_del_clean(&list, mem)); + if (!mem) + return (lst_list_clean(&list), perror("malloc"), exit(EXIT_FAILURE)); + new = lst_node_new(mem, del); + if (!new) + return (del(mem), lst_list_clean(&list), \ + terminal_raw_mode_disable(ECHOCTL | ICANON), \ + p_stderr(STDERR_FILENO, "minishell: %s", "lst_node_malloc"), \ + perror(""), exit(EXIT_FAILURE)); + lst_add_back(&list, new); +} + +int p_stderr(int stderr_fd, const char *error, const char *specifier) +{ + int old_stdout; + int count; + + old_stdout = dup(STDOUT_FILENO); + if (old_stdout == -1) + return (perror("dup"), -1); + if (dup2(stderr_fd, STDOUT_FILENO) == -1) + return (perror("dup2"), close(old_stdout), -1); + count = ft_printf(error, specifier); + ft_close(STDOUT_FILENO, "in p_stderr"); + if (dup2(old_stdout, STDOUT_FILENO) == -1) + return (perror("dup2"), close(old_stdout), -1); + ft_close(old_stdout, "in p_stderr"); + return (count); +} diff --git a/src/minishell.c b/src/minishell.c new file mode 100644 index 0000000..0f9d35a --- /dev/null +++ b/src/minishell.c @@ -0,0 +1,43 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* minishell.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: anarama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/07/05 12:22:34 by victor #+# #+# */ +/* Updated: 2024/08/27 17:12:24 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +int32_t volatile g_signal_flag; + +int main(int argc, const char **argv, const char **env) +{ + char *command_input; + char **environment; + int32_t exit_status; + int32_t std[2]; + + environment = environment_create(env); + setup(argc, argv, environment, std); + exit_status = 0; + while (g_signal_flag != 2) + { + g_signal_flag = 0; + env_static(environment); + command_input = prompt_get(NULL); + if (g_signal_flag == 2) + exit_status = 0; + else if (g_signal_flag == 1) + exit_status = 130; + else + m_tokenizer(command_input, environment, &exit_status, std); + if (g_signal_flag == 3) + exit_status = 131; + } + ft_putendl_fd("exit", 2); + return (lst_memory(NULL, NULL, END), exit_status); +} diff --git a/src/non_interactive.c b/src/non_interactive.c new file mode 100644 index 0000000..1018f8a --- /dev/null +++ b/src/non_interactive.c @@ -0,0 +1,131 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* non_interactive.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: victor +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/19 23:13:31 by victor #+# #+# */ +/* Updated: 2024/08/27 16:58:26 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +int32_t minishell_single_command( char *command, \ + char **environment, \ + int32_t std[2]) +{ + int32_t exit_status; + uint32_t input_length; + + exit_status = 0; + input_length = ft_strlen(command); + if (input_length) + { + if (command[input_length - 1] == '\n') + command[input_length - 1] = 0; + m_tokenizer(command, environment, &exit_status, std); + } + lst_memory(NULL, NULL, END); + exit(exit_status); +} + +void *ft_realloc_string(char **string, uint32_t *new_size) +{ + char *tmp; + + *new_size += *new_size; + tmp = ft_calloc(*new_size, sizeof(*tmp)); + lst_memory(tmp, free, ADD); + ft_memcpy(tmp, *string, ft_strlen(*string)); + lst_memory(*string, NULL, FREE); + *string = NULL; + return (tmp); +} + +char *check_redir_input(void) +{ + char *input; + char buffer[512]; + uint32_t capacity; + int64_t bytes_read; + + bytes_read = 1; + capacity = 512; + input = ft_calloc(capacity, sizeof(*input)); + lst_memory(input, free, ADD); + while (bytes_read) + { + ft_bzero(&buffer, sizeof(buffer)); + bytes_read = ft_read(0, buffer, 511); + if (bytes_read > 0) + { + if ((ft_strlen(input) + ft_strlen(buffer)) > capacity) + input = ft_realloc_string(&input, &capacity); + ft_strlcpy(input + ft_strlen(input), \ + buffer, ft_strlen(input) + ft_strlen(buffer) + 1); + } + else if (bytes_read < 0) + return (perror("read"), lst_memory(NULL, NULL, CLEAN), NULL); + } + return (input); +} + +void setup_environment(const char **environment) +{ + char *shlvl; + uint16_t shlvl_value; + + g_signal_flag = 0; + env_static((char **)environment); + setup_signal_handlers(); + shlvl_value = ft_atoi(environment_variable_value_get("SHLVL", \ + (const char **)environment)) + 1; + if (shlvl_value == 1000) + { + ft_putendl_fd("minishell: \ + warning: shell level (1000) too high, resetting to 1", 2); + shlvl = ft_strdup("1"); + } + else + shlvl = ft_itoa(shlvl_value); + if (!shlvl) + { + perror("malloc"); + lst_memory(NULL, NULL, CLEAN); + } + environment_variable_value_change((const char **)environment, \ + "SHLVL", shlvl); + ft_free(&shlvl); +} + +int setup( uint32_t argc, \ + const char **argv, \ + char **environment, \ + int32_t std[2]) +{ + char *input; + + setup_environment((const char **)environment); + std[0] = dup(STDIN_FILENO); + std[1] = dup(STDOUT_FILENO); + if (std[0] == -1 || std[1] == -1) + return (perror("dup"), lst_memory(NULL, NULL, CLEAN), 1); + lst_memory(std, close_fds, ADD); + if (!isatty(0)) + { + input = check_redir_input(); + if (input) + minishell_single_command(input, environment, std); + } + else if (argc > 1) + { + if (argc > 2) + return (-1); + else + return (minishell_single_command((char *)argv[1], \ + environment, std)); + } + return (1); +} diff --git a/src/path_utils.c b/src/path_utils.c new file mode 100644 index 0000000..dd157bc --- /dev/null +++ b/src/path_utils.c @@ -0,0 +1,133 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* path_utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: anarama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/07/07 19:32:35 by anarama #+# #+# */ +/* Updated: 2025/02/15 15:24:08 by victor ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +static int find_longest_path(const char *path) +{ + int i; + int ret; + + i = 0; + ret = 0; + if (!path) + return (0); + while (*path++) + { + if (*path == ':' || !*path) + { + if (ret < i) + { + ret = i; + i = 0; + } + } + i++; + } + if (ret) + return (ret); + return (i); +} + +bool isdir(char *input) +{ + struct stat dir; + + dir = (struct stat){0}; + stat(input, &dir); + if (S_ISDIR(dir.st_mode)) + return (true); + return (false); +} + +static char *print_error(char *input, int *exit_status) +{ + if (input && ft_strchr(input, '/')) + { + if (input && isdir(input)) + return (p_stderr(2, "minishell: %s: Is a directory\n", input), \ + *exit_status = 126, NULL); + if (access(input, F_OK) == 0) + { + if (access(input, X_OK) == 0) + return (input); + else + { + p_stderr(STDERR_FILENO, "minishell: %s: Permission denied\n", \ + input); + *exit_status = 126; + } + } + else + return (p_stderr(STDERR_FILENO, \ + "minishell: %s: No such file or directory\n", \ + input), *exit_status = 127, NULL); + } + else + return (*exit_status = 127, p_stderr(STDERR_FILENO, \ + "minishell: %s: command not found\n", input), NULL); + return (NULL); +} + +static char *check_paths( const char *path, \ + char *path_abs, \ + char *input, \ + int *exit_status) +{ + char *tmp; + + if (ft_memcmp(input, ".", 2) != 0 && ft_memcmp(input, "..", 3) != 0) + { + while (path) + { + tmp = ft_strchr(path, ':'); + if (!tmp) + tmp = ft_strchr(path, '\0'); + if (tmp) + { + ft_strlcpy(path_abs, path, tmp - path + 1); + ft_strlcat(path_abs, "/", ft_strlen(path_abs) + 2); + ft_strlcat(path_abs, input, \ + ft_strlen(input) + ft_strlen(path_abs) + 1); + } + if (access(path_abs, F_OK) == 0) + { + if (access(path_abs, X_OK) == 0) + return (path_abs); + } + path = ft_strchr(path, ':'); + if (path) + path++; + } + } + return (print_error(input, exit_status)); +} + +char *find_absolute_path( const char *path_variable, \ + char *input, \ + int *exit_status) +{ + char *path_abs; + uint32_t path_length; + + if (!input) + return (NULL); + if ((input && *input == 0) || ft_strchr(input, '/') || !path_variable) + return (print_error(input, exit_status)); + path_variable = ft_strchr(path_variable, '/'); + path_length = find_longest_path(path_variable); + if (!path_length) + return (NULL); + path_abs = malloc(path_length + ft_strlen(input) + 2); + lst_memory(path_abs, &free, ADD); + return (check_paths(path_variable, path_abs, input, exit_status)); +} diff --git a/src/termios.c b/src/termios.c new file mode 100644 index 0000000..154d65a --- /dev/null +++ b/src/termios.c @@ -0,0 +1,37 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* termios.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: anarama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/07/16 09:46:56 by vvobis #+# #+# */ +/* Updated: 2024/08/04 13:25:04 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +void terminal_raw_mode_enable(int flag) +{ + struct termios raw; + + if (isatty(0) && isatty(1)) + { + tcgetattr(STDIN_FILENO, &raw); + raw.c_lflag &= ~(flag); + tcsetattr(STDIN_FILENO, TCSANOW, &raw); + } +} + +void terminal_raw_mode_disable(int flag) +{ + struct termios orig; + + if (isatty(0) && isatty(1)) + { + tcgetattr(STDIN_FILENO, &orig); + orig.c_lflag |= (flag); + tcsetattr(STDIN_FILENO, TCSANOW, &orig); + } +} diff --git a/src/utils.c b/src/utils.c new file mode 100644 index 0000000..26dead3 --- /dev/null +++ b/src/utils.c @@ -0,0 +1,50 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: anarama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/08 12:07:59 by victor #+# #+# */ +/* Updated: 2024/08/24 12:54:28 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +char **env_static(char **environment) +{ + static char **env; + + if (environment) + env = environment; + return (env); +} + +void ft_opendir(DIR **directory, const char *directory_path) +{ + *directory = opendir(directory_path); + if (*directory == NULL) + { + p_stderr(2, "directory: %s: ", directory_path); + perror("opendir"); + } +} + +int64_t ft_read(int fd, char *character, uint32_t size_to_read) +{ + int64_t bytes_read; + + bytes_read = read(fd, character, size_to_read); + if (bytes_read == -1) + { + if (errno == EINTR \ + || errno == EAGAIN \ + || errno == EWOULDBLOCK \ + || g_signal_flag == 1) + return (0); + perror("read"); + lst_memory(NULL, NULL, CLEAN); + } + return (bytes_read); +} diff --git a/src/utils2.c b/src/utils2.c new file mode 100644 index 0000000..21098b6 --- /dev/null +++ b/src/utils2.c @@ -0,0 +1,73 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* utils2.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: anarama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/07/15 13:50:41 by anarama #+# #+# */ +/* Updated: 2024/08/19 22:57:39 by victor ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +void custom_memmove_strings(char **dest, char **src) +{ + char *temp; + + temp = NULL; + while (*src) + { + temp = ft_strdup(*src); + if (!temp) + { + lst_memory(NULL, NULL, CLEAN); + } + free(*dest); + *dest = temp; + temp = NULL; + dest++; + src++; + } + while (*dest) + { + free(*dest); + *dest = NULL; + dest++; + } +} + +int get_tokens_count(char **tokens) +{ + int i; + + i = 0; + while (*tokens) + { + tokens++; + i++; + } + return (i); +} + +void *ft_realloc(void *ptr, int old_size, int new_size) +{ + void *new_ptr; + + if (!new_size) + { + free(ptr); + return (NULL); + } + if (!ptr) + { + new_ptr = ft_calloc(new_size, 1); + return (new_ptr); + } + new_ptr = ft_calloc(new_size, 1); + if (!new_ptr) + return (NULL); + ft_memcpy(new_ptr, ptr, old_size); + return (new_ptr); +} diff --git a/src/utils3.c b/src/utils3.c new file mode 100644 index 0000000..153e1a5 --- /dev/null +++ b/src/utils3.c @@ -0,0 +1,68 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* utils3.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/02 17:32:16 by vvobis #+# #+# */ +/* Updated: 2024/08/26 11:46:25 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" +#include + +int ft_close(int fd, const char *specifier) +{ + if (fd == -1) + return (0); + if (close(fd) == -1) + { + p_stderr(2, "minishell: %s: ", specifier); + perror("close"); + } + return (1); +} + +void ft_pipe(int pipefd[2], const char *specifier) +{ + if (pipe(pipefd) == -1) + { + p_stderr(2, "minishell: %s: ", specifier); + perror("pipe"); + } +} + +void ft_dup2(int fd_old, int fd_new, const char *specifier) +{ + if (dup2(fd_old, fd_new) == -1) + { + p_stderr(2, "minishell: %s: ", specifier); + perror("dup2"); + } +} + +void ft_fork(pid_t *pid, const char *specifier) +{ + *pid = fork(); + if (*pid == -1) + { + p_stderr(2, "minishell: %s: ", specifier); + perror("fork"); + lst_memory(NULL, NULL, CLEAN); + } +} + +void ft_open(int *fd, const char *path, int flag, int mode) +{ + if (mode > 0) + *fd = open(path, flag, mode); + else + *fd = open(path, flag); + if (*fd == -1) + { + ft_putstr_fd("minishell: ", 2); + perror(path); + } +} diff --git a/src/wildcards.c b/src/wildcards.c new file mode 100644 index 0000000..6bbbb5d --- /dev/null +++ b/src/wildcards.c @@ -0,0 +1,111 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* wildcards.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: anarama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/05 21:02:23 by anarama #+# #+# */ +/* Updated: 2024/08/23 11:02:09 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +void copy_wildcards(int *k, int *j, char **matches, + char **new_tokens) +{ + while (matches[*j] != NULL) + { + new_tokens[*k] = matches[*j]; + (*k)++; + (*j)++; + } +} + +void copy_old_tokens(int *k, int i, char **new_tokens, + char **old_tokens) +{ + new_tokens[*k] = old_tokens[i]; + (*k)++; +} + +void copy_tokens_with_wildcards(char **new_args, + char **old_args, char **matches) +{ + int flag; + int i; + int j; + int k; + + flag = 1; + i = 0; + j = 0; + k = 0; + while (old_args[i] != NULL) + { + if (flag == 1 && check_wildcard(old_args[i])) + { + copy_wildcards(&k, &j, matches, new_args); + flag = 0; + } + else + { + copy_old_tokens(&k, i, new_args, old_args); + } + i++; + } + new_args[k] = NULL; +} + +int handle_wildcard(char ***args, char ***new_args, + int i, int *size) +{ + char **matches; + int match_count; + int match_found; + + matches = expand_wildcard((*args)[i]); + match_found = 0; + if (matches) + { + match_found = 1; + match_count = get_tokens_count(matches); + if (*new_args != NULL) + lst_memory(*new_args, free, ADD); + *new_args = ft_realloc(*new_args, *size * sizeof(char *), + (*size + match_count) * sizeof(char *)); + *size = *size + match_count - 1; + copy_tokens_with_wildcards(*new_args, *args, matches); + *args = *new_args; + } + return (match_found); +} + +void check_and_expand_wildcards(char ***input) +{ + char **args; + char **new_args; + int match_found; + int size; + int i; + + if (!*input) + return ; + match_found = 0; + args = *input; + size = get_split_size((const char **)*input); + new_args = NULL; + i = 0; + while (args[i] != NULL) + { + if (check_wildcard(args[i])) + match_found += handle_wildcard(&args, &new_args, i, &size); + i++; + } + if (match_found) + { + free(*input); + *input = args; + } +} diff --git a/src/wildcards_hanlde_match.c b/src/wildcards_hanlde_match.c new file mode 100644 index 0000000..23efdfb --- /dev/null +++ b/src/wildcards_hanlde_match.c @@ -0,0 +1,81 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* wildcards_hanlde_match.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: victor +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/19 23:00:51 by victor #+# #+# */ +/* Updated: 2024/08/26 15:39:58 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +int compare_suffix(const char *current_position_in_str, + const char *current_position_in_pattern) +{ + const char *suffix; + size_t len_current_pattern; + size_t len_current_str; + + len_current_pattern = ft_strlen(current_position_in_pattern); + len_current_str = ft_strlen(current_position_in_str); + if (len_current_pattern > len_current_str) + return (-1); + suffix = current_position_in_str + len_current_str + - len_current_pattern; + return (ft_strncmp(current_position_in_pattern, suffix, + len_current_pattern)); +} + +int handle_prefix(const char *pattern, const char *str, + char *adr_next_wild) +{ + size_t len_prefix; + + len_prefix = adr_next_wild - pattern; + if (len_prefix == 0 && str[0] == *(adr_next_wild + 1)) + return (-1); + return (ft_strncmp(pattern, str, len_prefix)); +} + +int handle_suffix(const char *current_position_in_pattern, + const char *current_position_in_str) +{ + if (*current_position_in_pattern != '\0') + { + if (compare_suffix(current_position_in_str, + current_position_in_pattern) != 0) + return (-1); + } + return (0); +} + +int handle_middle(const char *pattern, const char *str) +{ + const char *current_position_in_pattern; + const char *current_position_in_str; + char *adr_next_wild; + char *result; + int len_current_pattern; + + adr_next_wild = ft_strchr(pattern, '*'); + current_position_in_pattern = pattern; + current_position_in_str = str; + result = 0; + while (adr_next_wild) + { + *((char *)adr_next_wild) = 0; + len_current_pattern = adr_next_wild - current_position_in_pattern; + result = ft_strnstr(str, current_position_in_pattern, ft_strlen(str)); + *((char *)adr_next_wild) = '*'; + if (!result) + return (-1); + current_position_in_str = result + len_current_pattern; + current_position_in_pattern = adr_next_wild + 1; + adr_next_wild = ft_strchr(current_position_in_pattern, '*'); + } + return (handle_suffix(current_position_in_pattern, + current_position_in_str)); +} diff --git a/src/wildcards_helper.c b/src/wildcards_helper.c new file mode 100644 index 0000000..3b2f00a --- /dev/null +++ b/src/wildcards_helper.c @@ -0,0 +1,108 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* wildcards_helper.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: victor +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/19 23:04:15 by victor #+# #+# */ +/* Updated: 2024/08/26 15:45:44 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +int match_found(const char *pattern, const char *str) +{ + char *adr_next_wild; + int len_prefix; + + if (*pattern == '*' && *(pattern + 1) == '\0') + { + if (str[0] == '.') + return (1); + return (0); + } + adr_next_wild = ft_strchr(pattern, '*'); + if (adr_next_wild) + { + if (handle_prefix(pattern, str, adr_next_wild) != 0) + return (-1); + len_prefix = adr_next_wild - pattern; + pattern += len_prefix + 1; + str += len_prefix; + } + return (handle_middle(pattern, str)); +} + +void lst_calloc(void **ptr, int num, int size) +{ + *ptr = ft_calloc(num, size); + if (!*ptr) + { + perror("calloc wildcards"); + lst_memory(NULL, NULL, CLEAN); + } + lst_memory(*ptr, free, ADD); +} + +void add_new_match(int *count, int *capacity, + char ***matches, char *entry_name) +{ + if (*count >= *capacity) + { + *matches = (char **)ft_realloc(*matches, *count * sizeof(char *), + (*count * 2 + 1) * sizeof(char *)); + if (!*matches) + { + perror("calloc wildcards"); + lst_memory(NULL, NULL, CLEAN); + } + lst_memory(*matches, free, ADD); + *capacity *= 2; + } + (*matches)[*count] = ft_strdup(entry_name); + if (!(*matches)[*count]) + { + perror("strdup wildcards"); + lst_memory(NULL, NULL, CLEAN); + } + lst_memory((*matches)[*count], free, ADD); + (*count)++; +} + +char **expand_wildcard(const char *pattern) +{ + struct dirent *entry; + char **matches; + DIR *dir; + int capacity; + int count; + + capacity = 10; + matches = NULL; + count = 0; + ft_opendir(&dir, "."); + entry = readdir(dir); + lst_calloc((void **)&matches, capacity + 1, sizeof(char *)); + while (entry != NULL) + { + if (match_found(pattern, entry->d_name) == 0) + { + add_new_match(&count, &capacity, + &matches, entry->d_name); + } + entry = readdir(dir); + } + closedir(dir); + if (count == 0) + return (NULL); + return (matches); +} + +int check_wildcard(char *str) +{ + if (!str) + return (0); + return (ft_strchr(str, '*') != NULL); +} diff --git a/tokenizer/check_special_symbol.c b/tokenizer/check_special_symbol.c new file mode 100644 index 0000000..afc877e --- /dev/null +++ b/tokenizer/check_special_symbol.c @@ -0,0 +1,48 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* check_special_symbol.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: anarama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/07/20 19:44:00 by anarama #+# #+# */ +/* Updated: 2024/08/21 10:51:22 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +int is_special_char(char c) +{ + return (c == ' ' || c == '|' || c == '>' || c == '$' + || c == '<' || c == '&' || c == ';'); +} + +int ft_isspace(char c) +{ + return (c == ' ' || c == '\t' || c == '\v' + || c == '\f' || c == '\r' || c == '\n'); +} + +bool unrecognized_input(char c) +{ + if (c >= 0 && c < 127 && (ft_isalnum(c) \ + || ft_isspace(c) || is_special_char(c) \ + || c == '?' || c == '/' || c == '-' || c == '\n' \ + || c == ';' || c == '\'' || c == '\"' || c == '.'\ + || c == '(' || c == ')' || c == '*' || c == '[' \ + || c == ']' || c == '{' || c == '}' || c == '#')) + return (false); + p_stderr(2, "minishell: syntax error near unexpected token `%s'\n", \ + (char []){c, 0}); + return (true); +} + +bool is_in_alphabet(char c) +{ + return (is_special_char(c) \ + || c == '/' || c == '?' \ + || c == '-' || c == '\n' \ + || c == ';' || c == '\'' \ + || c == '\"' || c == '*' || c == '.'); +} diff --git a/tokenizer/create_token.c b/tokenizer/create_token.c new file mode 100644 index 0000000..91b5547 --- /dev/null +++ b/tokenizer/create_token.c @@ -0,0 +1,22 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* create_token.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: anarama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/07/20 19:47:21 by anarama #+# #+# */ +/* Updated: 2024/07/22 13:07:13 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +t_token create_token(t_token_type token_type, const char *value) +{ + t_token token; + + token.token_type = token_type; + token.token_value = (char *)value; + return (token); +} diff --git a/tokenizer/create_token_double_special_symbol.c b/tokenizer/create_token_double_special_symbol.c new file mode 100644 index 0000000..9971164 --- /dev/null +++ b/tokenizer/create_token_double_special_symbol.c @@ -0,0 +1,108 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* create_token_double_special_symbol.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: anarama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/07/21 12:35:12 by anarama #+# #+# */ +/* Updated: 2024/08/27 17:22:18 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" +#include +#include +#include +#include +#include + +int is_double_special(const char *input) +{ + return ((ft_strncmp(input, ">>", 2) == 0) + || (ft_strncmp(input, "<<", 2) == 0) + || (ft_strncmp(input, "&&", 2) == 0) + || (ft_strncmp(input, "||", 2) == 0)); +} + +bool is_mutliple_lines(char *c) +{ + bool has_mulitple_lines; + + has_mulitple_lines = false; + while (*c) + { + if (*c == '\n' && !has_mulitple_lines) + has_mulitple_lines = true; + else if (*c == '\n' && has_mulitple_lines) + return (true); + c++; + } + return (false); +} + +void remove_qoutes_delimiter(char *delimiter, uint32_t *length) +{ + uint32_t i; + uint32_t full_length; + + while (ft_isspace(*delimiter)) + delimiter++; + if (!(*delimiter == '\"' || *delimiter == '\'')) + return ; + i = 0; + full_length = ft_strlen(delimiter); + if (!length) + length = &full_length; + while (i < *length) + { + if (delimiter[i] == '\"' || delimiter[i] == '\'') + { + ft_memmove(&delimiter[i], &delimiter[i + 1], full_length - i); + (*length)--; + } + i++; + } +} + +t_token create_token_heredoc(char **input) +{ + t_token temp_token; + + *input += 2; + while (**input && **input == ' ' && (!is_special_char(*((*input) + 1)) \ + || (*(*input) + 1 == '$'))) + (*input)++; + temp_token = create_token(TOKEN_HEREDOC, *input); + if (!isatty(0)) + *input = heredoc_while_tokenizing(*input); + else + while (**input && !ft_isspace(**input) \ + && !is_special_char(*((*input) + 1))) + (*input)++; + if (**input && !is_special_char(**input)) + { + **input = 0; + (*input)++; + } + return (temp_token); +} + +t_token create_token_double_special_symbol(char **input) +{ + t_token temp_token; + t_token_type token_type; + + if (ft_strncmp(*input, ">>", 2) == 0) + token_type = TOKEN_REDIRECT_APPEND; + else if (ft_strncmp(*input, "<<", 2) == 0) + token_type = TOKEN_HEREDOC; + else if (ft_strncmp(*input, "&&", 2) == 0) + token_type = TOKEN_AND; + else + token_type = TOKEN_OR; + temp_token = create_token(token_type, NULL); + **input = 0; + *input += 2; + return (temp_token); +} diff --git a/tokenizer/create_token_single_special_symbol.c b/tokenizer/create_token_single_special_symbol.c new file mode 100644 index 0000000..f873dae --- /dev/null +++ b/tokenizer/create_token_single_special_symbol.c @@ -0,0 +1,48 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* create_token_single_special_symbol.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: anarama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/07/21 12:36:57 by anarama #+# #+# */ +/* Updated: 2024/07/28 19:45:39 by victor ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +int is_single_special(const char input) +{ + return ((input == '<') + || (input == '>') + || (input == '|')); +} + +t_token create_token_single_special_symbol(const char **input) +{ + t_token temp_token; + uint32_t i; + char *temp_move; + + i = 0; + temp_move = (char *)*input; + if (**input == '<') + temp_token = create_token(TOKEN_REDIRECT_IN, &(*input)[i]); + else if (**input == '>') + temp_token = create_token(TOKEN_REDIRECT_OUT, &(*input)[i]); + else + temp_token = create_token(TOKEN_PIPE, &(*input)[i]); + if (temp_move) + { + *temp_move = 0; + *input = temp_move + 1; + } + else + { + temp_move = (char *)*input; + *input += ft_strlen(*input); + *temp_move = 0; + } + return (temp_token); +} diff --git a/tokenizer/create_token_word.c b/tokenizer/create_token_word.c new file mode 100644 index 0000000..94a64e4 --- /dev/null +++ b/tokenizer/create_token_word.c @@ -0,0 +1,51 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* create_token_word.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: anarama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/07/21 12:40:09 by anarama #+# #+# */ +/* Updated: 2024/08/22 16:45:38 by victor ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +void skip_to_end_quotes(char **temp_move, char c) +{ + (*temp_move)++; + while (**temp_move && **temp_move != c) + (*temp_move)++; + if (**temp_move) + (*temp_move)++; +} + +t_token create_token_word(const char **input) +{ + t_token temp_token; + char *temp_move; + char *input_next; + + temp_move = (char *)*input; + temp_token = create_token(TOKEN_WORD, *input); + if (**input == '$') + temp_move++; + while (*temp_move && !ft_isspace(*temp_move) \ + && (!is_special_char(*temp_move) || *temp_move == '$')) + { + if (*temp_move == '\'' || *temp_move == '\"') + skip_to_end_quotes(&temp_move, *temp_move); + else + temp_move++; + } + if (*temp_move && ft_isspace(*temp_move) && *temp_move != '\n') + { + *temp_move = 0; + input_next = temp_move + 1; + } + else + input_next = temp_move; + *input = input_next; + return (temp_token); +} diff --git a/tokenizer/evaluate_input.c b/tokenizer/evaluate_input.c new file mode 100644 index 0000000..bd3dfe9 --- /dev/null +++ b/tokenizer/evaluate_input.c @@ -0,0 +1,132 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* evaluate_input.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: anarama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/07/31 14:40:58 by vvobis #+# #+# */ +/* Updated: 2024/08/27 15:21:21 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +char *insert_exit_status( char *input_new, \ + int32_t *exit_status, \ + uint32_t input_length) +{ + char *exit_status_string; + + ft_memmove(input_new, input_new + 1, input_length); + exit_status_string = ft_itoa(*exit_status); + if (exit_status_string) + { + ft_memmove(input_new + ft_strlen(exit_status_string), \ + input_new, input_length); + ft_memcpy(input_new, exit_status_string, \ + ft_strlen(exit_status_string)); + } + ft_free(&exit_status_string); + return (NULL); +} + +bool insert_string( char *new_string, \ + uint32_t *i, char **environment, \ + int32_t *exit_status) +{ + char *temp_move; + char *variable; + char character_store; + uint32_t length; + + temp_move = new_string; + ft_memmove(temp_move, temp_move + 1, ft_strlen(temp_move)); + if (*temp_move == '?') + return (insert_exit_status(temp_move, exit_status, \ + ft_strlen(new_string))); + character_store = skip_to_delimiter(temp_move); + variable = environment_variable_value_get(temp_move, \ + (const char **)environment); + length = ft_strlen(temp_move); + temp_move[ft_strlen(temp_move)] = character_store; + ft_memmove(temp_move + ft_strlen(variable), \ + temp_move + length, ft_strlen(temp_move)); + ft_memcpy(temp_move, variable, ft_strlen(variable)); + *i += ft_strlen(variable) - 1; + return (true); +} + +char *evaluate_helper(char *string_to_change, \ + int32_t *exit_status) +{ + bool in_double_quotes; + char *new_string; + uint i; + + in_double_quotes = false; + i = 0; + new_string = NULL; + while (string_to_change[i]) + { + if (skip_single_quotes(string_to_change, &i, &in_double_quotes)) + return (NULL); + if (string_to_change[i] == '$' && \ + !is_delimiter_variable(string_to_change[i + 1])) + { + new_string = ft_calloc(determine_full_length(string_to_change, \ + env_static(NULL)) + 1, sizeof(*new_string)); + lst_memory(new_string, free, ADD); + ft_memcpy(new_string, string_to_change, \ + ft_strlen(string_to_change)); + insert_string(&new_string[i], &i, env_static(NULL), exit_status); + string_to_change = new_string; + } + i++; + } + return (new_string); +} + +char **determine_new_size(char **input) +{ + uint32_t split_length; + uint32_t capacity; + uint32_t new_size; + char **input_new; + + split_length = get_split_size((const char **)input); + capacity = split_length + (INITIAL_TOKEN_CAPACITY - \ + (split_length % INITIAL_TOKEN_CAPACITY)); + new_size = determine_variables(input); + if (new_size >= capacity - 1) + { + new_size = new_size + (INITIAL_TOKEN_CAPACITY - \ + (new_size % INITIAL_TOKEN_CAPACITY)); + input_new = ft_calloc(new_size, sizeof(*input_new)); + lst_memory(input_new, free, ADD); + ft_memcpy(input_new, *input, split_length); + return (input_new); + } + return (input); +} + +uint32_t evaluate_variable( char ***input, \ + int32_t *exit_status) +{ + char *new_string; + uint32_t i; + + *input = determine_new_size(*input); + i = 0; + while ((*input)[i]) + { + if (ft_strchr((*input)[i], '$')) + { + new_string = evaluate_helper((*input)[i], exit_status); + if (new_string) + adjust_input(&(*input)[i], new_string); + } + i++; + } + return (false); +} diff --git a/tokenizer/evaluate_input_helper.c b/tokenizer/evaluate_input_helper.c new file mode 100644 index 0000000..0c814b1 --- /dev/null +++ b/tokenizer/evaluate_input_helper.c @@ -0,0 +1,129 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* evaluate_input_helper.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/27 15:10:37 by vvobis #+# #+# */ +/* Updated: 2024/08/27 15:20:08 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +uint32_t get_spaces(char *input) +{ + uint32_t i; + uint32_t counter; + char character_store; + + i = 0; + counter = 0; + while (input[i]) + { + if (input[i] == '\"' || input[i] == '\'') + { + character_store = input[i]; + while (input[i] && input[i] != character_store) + i++; + } + if (input[i] == ' ') + counter++; + i++; + } + return (counter); +} + +uint32_t determine_variables(char **input) +{ + uint i; + uint j; + uint counter; + char *tmp; + char character_store; + + i = -1; + counter = 1; + while (input[++i]) + { + j = -1; + while (input[i][++j]) + { + if (input[i][j] == '$') + { + character_store = skip_to_delimiter(&input[i][j + 1]); + tmp = environment_variable_value_get(&input[i][j + 1], \ + (const char **)env_static(NULL)); + if (tmp) + counter += get_spaces(tmp) + 1; + input[i][ft_strlen(input[i])] = character_store; + } + } + } + return (counter); +} + +void split_string_by_space(char *to_split, char **input_new) +{ + uint32_t i; + char character_store; + + i = 0; + input_new[i++] = to_split; + while (*to_split) + { + if (*to_split == '\"' || *to_split == '\'') + { + character_store = *to_split++; + while (*to_split && *to_split != character_store) + to_split++; + } + if (*to_split == ' ') + { + *to_split = 0; + input_new[i++] = to_split + 1; + } + to_split++; + } +} + +void adjust_input(char **input, char *new_string) +{ + uint32_t count; + + count = get_spaces(new_string) + 1; + if (count) + ft_memmove(input + count, input + 1, \ + get_split_size((const char **)input) * sizeof(*input)); + split_string_by_space(new_string, input); +} + +uint32_t determine_full_length(char *string, char **environment) +{ + uint32_t size; + uint32_t i; + char character_store; + + size = 0; + i = 0; + character_store = 0; + while (string[i]) + { + if (string[i] == '$') + { + character_store = skip_to_delimiter(&string[i + 1]); + if (string[i] == '?') + size += 4; + else + size += ft_strlen(environment_variable_value_get(\ + &string[i + 1], (const char **)environment)); + while (string[i]) + i++; + string[i] = character_store; + } + else + i++; + } + return (size + i); +} diff --git a/tokenizer/evaluate_input_helper2.c b/tokenizer/evaluate_input_helper2.c new file mode 100644 index 0000000..78b02ec --- /dev/null +++ b/tokenizer/evaluate_input_helper2.c @@ -0,0 +1,40 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* evaluate_input_helper2.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/27 15:21:09 by vvobis #+# #+# */ +/* Updated: 2024/08/27 15:21:20 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +void evaluate_input( char **input[], \ + int32_t *exit_status, \ + bool *error_caught) +{ + uint32_t i; + uint32_t j; + bool dummy; + + i = 0; + dummy = false; + if (!error_caught) + error_caught = &dummy; + *error_caught = evaluate_variable(input, exit_status); + while (*input && (*input)[i] && !*error_caught) + { + j = -1; + while ((*input)[i][++j] && !*error_caught) + { + if ((*input)[i][j] == '\"') + *error_caught = evaluate_double_quotes((*input)[i], &j); + else if ((*input)[i][j] == '\'') + *error_caught = evaluate_single_quotes((*input)[i], &j); + } + i++; + } +} diff --git a/tokenizer/input_skip_patterns.c b/tokenizer/input_skip_patterns.c new file mode 100644 index 0000000..fcc28f1 --- /dev/null +++ b/tokenizer/input_skip_patterns.c @@ -0,0 +1,94 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* input_skip_patterns.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/21 10:27:01 by vvobis #+# #+# */ +/* Updated: 2024/08/21 11:13:32 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +bool is_delimiter_variable(char c) +{ + return (ft_isspace(c) || c == '\'' || c == '\"' || c == '$' || c == 0); +} + +char skip_to_delimiter(char *input_new) +{ + char *temp_move; + char character_store; + + temp_move = input_new; + while (ft_isalnum(*temp_move) || *temp_move == '?' || *temp_move == '_') + { + temp_move++; + } + character_store = *temp_move; + *temp_move = 0; + return (character_store); +} + +bool skip_single_quotes(char *input, uint32_t *i, bool *in_double_quotes) +{ + char *temp_move; + + temp_move = input; + if (input[*i] == '\"' && !*in_double_quotes) + *in_double_quotes = true; + else if (input[*i] == '\"' && *in_double_quotes) + *in_double_quotes = false; + if (input[*i] == '\'' && !*in_double_quotes) + { + temp_move = ft_strchr(&input[*i + 1], '\''); + if (!temp_move) + return (\ + ft_putendl_fd("minishell: missing closing single quote", 2), true); + else + *i = temp_move - input; + } + return (false); +} + +bool evaluate_double_quotes(char *input, uint32_t *i) +{ + uint32_t input_length; + + input_length = ft_strlen(&input[*i]); + ft_memmove(&input[*i], &input[*i + 1], input_length); + while (input[*i]) + { + if (input[*i] == '\"') + { + ft_memmove(&input[*i], &input[*i + 1], \ + ft_strlen(&input[*i])); + (*i)--; + return (false); + } + (*i)++; + } + return (ft_putendl_fd("minishell: missing closing double quote", 2), true); +} + +bool evaluate_single_quotes(char *input, uint32_t *i) +{ + uint32_t input_length; + + input_length = ft_strlen(&input[*i]); + ft_memmove(&input[*i], &input[*i + 1], input_length); + while (input[*i]) + { + if (input[*i] == '\'') + { + ft_memmove(&input[*i], &input[*i + 1], \ + ft_strlen(&input[*i])); + (*i)--; + return (false); + } + (*i)++; + } + return (ft_putendl_fd("minishell: missing closing single quote", 2), true); +} diff --git a/tokenizer/subshell.c b/tokenizer/subshell.c new file mode 100644 index 0000000..ed275f1 --- /dev/null +++ b/tokenizer/subshell.c @@ -0,0 +1,86 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* subshell.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/07/30 18:20:59 by vvobis #+# #+# */ +/* Updated: 2024/08/24 13:27:15 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" +#include + +static void subshell_child_execute( char *input, \ + const char **environement, \ + int32_t pipefd[2]) +{ + char *path_variable; + int32_t exit_status; + + exit_status = 0; + path_variable = environment_variable_value_get("PATH", environement); + if (!path_variable) + return ; + ft_close(pipefd[0], "pipefd[0] in child parent"); + ft_dup2(pipefd[1], STDOUT_FILENO, "execute_subshell stdout"); + ft_close(pipefd[1], "close in execute_subshell"); + m_tokenizer(input, (char **)environement, &exit_status, NULL); + lst_memory(NULL, NULL, END); + exit(exit_status); +} + +void manage_buffer_size_subshel(char **input_subshell, uint32_t *buffer_size) +{ + uint32_t buffer_strlen; + + buffer_strlen = ft_strlen(*input_subshell); + if (buffer_strlen == *buffer_size - 101) + prompt_buffer_size_manage(input_subshell, *buffer_size, \ + *buffer_size * 2, PROMPT_INPUT_BUFFER_SIZE); + *buffer_size *= 2; +} + +static void subshell_parent_execute(char **input_subshell, int32_t pipefd[2]) +{ + int64_t bytes_read; + uint32_t string_size; + + ft_close(pipefd[1], "close in execute_subshell"); + string_size = 0; + while (1) + { + bytes_read = read(pipefd[0], *input_subshell + string_size, 100); + if (bytes_read == -1) + { + perror("read"); + lst_memory(NULL, NULL, CLEAN); + } + else if (bytes_read == 0) + break ; + else + string_size += bytes_read; + } + ft_close(pipefd[0], "pipefd[0] in subshell parent"); +} + +char *execute_subshell(char *input, const char **environement) +{ + char *input_subshell; + int32_t pipefd[2]; + pid_t pid; + + input_subshell = NULL; + input_subshell = ft_calloc(PROMPT_INPUT_BUFFER_SIZE, \ + sizeof(*input_subshell)); + lst_memory(input_subshell, free, ADD); + ft_pipe(pipefd, "in execute_subshell"); + ft_fork(&pid, "execute_subshell"); + if (pid == 0) + subshell_child_execute(input, environement, pipefd); + else + subshell_parent_execute(&input_subshell, pipefd); + return (input_subshell); +} diff --git a/tokenizer/token_heredoc.c b/tokenizer/token_heredoc.c new file mode 100644 index 0000000..609a247 --- /dev/null +++ b/tokenizer/token_heredoc.c @@ -0,0 +1,121 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* token_heredoc.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/21 10:44:08 by vvobis #+# #+# */ +/* Updated: 2024/08/26 17:50:28 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" +#include + +static char *token_heredoc_input_get(t_prompt *heredoc, const char *delimiter) +{ + char *heredoc_input; + + heredoc_input = prompt_get_input(heredoc, \ + PROMPT_INPUT_BUFFER_SIZE, \ + delimiter); + if (!heredoc_input || !*heredoc_input) + { + if (g_signal_flag == 2 || g_signal_flag == 1) + g_signal_flag = 0; + return (NULL); + } + return (heredoc_input); +} + +void token_heredoc_get( t_token *token, \ + const char *delimiter) +{ + static t_prompt heredoc = {0}; + + if (heredoc.exists == false) + { + heredoc = prompt_create(CUSTOM); + heredoc.prompt_length = prompt_display_string_set(&heredoc, \ + NULL, \ + "heredoc> "); + } + token->token_value = token_heredoc_input_get(&heredoc, delimiter); + token->token_type = TOKEN_DONE; +} + +char *heredoc_loop( char *input, \ + char *temp_move, \ + const char *delimiter, \ + uint32_t delimiter_length) +{ + char *temp_cut; + uint32_t length; + uint32_t i; + + while (temp_move && *temp_move) + { + temp_cut = temp_move + 1; + while (*temp_cut && *temp_cut != '\n') + temp_cut++; + length = temp_cut - temp_move; + i = 0; + while (i < length) + { + ft_memmove(input + 1, input, ft_strlen(input)); + *input++ = *++temp_move; + ft_memmove(temp_move, temp_move + 1, ft_strlen(temp_move)); + i++; + } + if (length >= delimiter_length) + if (ft_memcmp(input - length + 1, \ + delimiter, length - 1) == 0) + break ; + temp_move = ft_strchr(temp_move, '\n'); + } + return (input); +} + +char *handle_delimiter(char *input, char **temp_move) +{ + char *delimiter; + uint32_t delimiter_length; + + delimiter = input; + while (ft_isspace(*delimiter)) + delimiter++; + delimiter_length = ft_strlen(delimiter); + remove_qoutes_delimiter(delimiter, &delimiter_length); + *temp_move = delimiter; + while (*temp_move && !ft_isspace(**temp_move) \ + && !is_single_special(**temp_move)) + { + if (**temp_move == '\'' || **temp_move == '\"') + ft_memmove(*temp_move, *temp_move + 1, ft_strlen(*temp_move)); + else + (*temp_move)++; + } + return (delimiter); +} + +char *heredoc_while_tokenizing(char *input) +{ + char *delimiter; + char *temp_move; + char character_store; + uint32_t delimiter_length; + + if (!is_mutliple_lines(input)) + return (input); + delimiter = handle_delimiter(input, &temp_move); + character_store = *temp_move; + *temp_move = 0; + delimiter_length = ft_strlen(delimiter); + *temp_move = character_store; + input = temp_move + (*temp_move != 0); + temp_move = input; + if (temp_move) + return (heredoc_loop(input, temp_move, delimiter, delimiter_length)); + return (input); +} diff --git a/tokenizer/tokenizer.c b/tokenizer/tokenizer.c new file mode 100644 index 0000000..020c351 --- /dev/null +++ b/tokenizer/tokenizer.c @@ -0,0 +1,97 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* tokenizer.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: anarama +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/07/16 19:49:35 by anarama #+# #+# */ +/* Updated: 2024/08/23 14:24:32 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" +#include + +static t_token *initialise_tokens(uint32_t word_count) +{ + t_token *tokens; + + if (word_count == 0) + return (NULL); + tokens = ft_calloc(word_count + 1, sizeof(t_token)); + lst_memory(tokens, free, ADD); + tokens[word_count].token_type = TOKEN_EOL; + return (tokens); +} + +static t_token check_symbol_and_create_token(const char **input) +{ + if (is_double_special(*input)) + return (create_token_double_special_symbol((char **)input)); + else if (is_single_special(**input)) + return (create_token_single_special_symbol(input)); + else if (**input) + return (create_token_word(input)); + else + return ((t_token){0, 0}); +} + +static uint32_t get_word_count(char *input) +{ + uint32_t i; + uint32_t word_count; + + i = 0; + word_count = 0; + while (input[i]) + { + while (ft_isspace(input[i])) + i++; + if (is_double_special(&input[i])) + i += 2; + else if (is_in_alphabet(input[i])) + i++; + else if (ft_isalnum(input[i])) + while (input[i] && !ft_isspace(input[i]) \ + && !is_double_special(&input[i]) && !is_special_char(input[i])) + i++; + else if (input[i]) + i++; + if (input[i] == '\n' || input[i] == ';') + word_count++; + word_count++; + } + return (word_count); +} + +t_token *tokens_setup(char *input) +{ + if (!input || !*input || *input == '\n' || *input == ';') + return (NULL); + if (input[ft_strlen(input) - 1] == '\n') + input[ft_strlen(input) - 1] = '\0'; + return (initialise_tokens(get_word_count((char *)input))); +} + +t_token *lexical_analysis(char *input) +{ + t_token *tokens; + uint32_t i; + t_ring_buffer heredoc_buffer; + + tokens = tokens_setup(input); + if (!tokens) + return (NULL); + i = -1; + heredoc_buffer = (t_ring_buffer){0}; + heredoc_buffer.buffer_capacity = BUFFER_CAPACITY; + while (*input) + { + tokenizing_loop(&input, tokens, &i, &heredoc_buffer); + tokens[++i] = check_symbol_and_create_token((const char **)&input); + if (tokens[i].token_type == TOKEN_HEREDOC) + ring_buffer_put(&heredoc_buffer, &tokens[i]); + } + return (tokens[++i].token_type = TOKEN_EOL, tokens); +} diff --git a/tokenizer/tokenizer_heredoc_helper.c b/tokenizer/tokenizer_heredoc_helper.c new file mode 100644 index 0000000..c5f0cc3 --- /dev/null +++ b/tokenizer/tokenizer_heredoc_helper.c @@ -0,0 +1,79 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* tokenizer_heredoc_helper.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: vvobis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/23 14:23:44 by vvobis #+# #+# */ +/* Updated: 2024/08/26 12:34:09 by vvobis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +t_token mark_tokens_till_heredoc(char *value, char **input) +{ + uint32_t value_length; + t_token token; + + *(*input)++ = 0; + token.token_value = *input; + token.token_type = TOKEN_WORD; + if (!value) + return (token); + value_length = 0; + while (value[value_length] && !ft_isspace(value[value_length]) \ + && (!is_special_char(value[value_length]) || value[value_length] == '$')) + value_length++; + remove_qoutes_delimiter(value, &value_length); + while (**input) + { + if (*(*input)++ == '\n') + if (ft_strncmp(value, *input, value_length) == 0 \ + && (*(*input + value_length) == '\n' \ + || *(*input + value_length) == '\0')) + return (*input += value_length, token); + } + return (token); +} + +void ring_buffer_put(t_ring_buffer *buffer, t_token *entry) +{ + if (buffer->write + 1 == buffer->read) + buffer->read++; + buffer->buffer[buffer->write++] = entry; + buffer->write %= buffer->buffer_capacity; +} + +t_token *ring_buffer_get(t_ring_buffer *buffer) +{ + t_token *entry; + + if (buffer->read == buffer->write) + return (NULL); + entry = buffer->buffer[buffer->read++]; + buffer->read %= buffer->buffer_capacity; + return (entry); +} + +void tokenizing_loop(char **input, \ + t_token *tokens, \ + uint32_t *i, \ + t_ring_buffer *heredoc_buffer) +{ + while (ft_isspace(**input) || **input == ';') + { + if (**input == '\n') + { + tokens[++*i].token_type = TOKEN_NEWLINE; + while (heredoc_buffer->read != heredoc_buffer->write) + tokens[++*i] = mark_tokens_till_heredoc(\ + ring_buffer_get(heredoc_buffer)[1].token_value, input); + } + else if (**input == ';') + tokens[++(*i)].token_type = TOKEN_SEMICOLON; + if (**input) + *(*input)++ = 0; + } +}