commit 196e143285318456ccc0275419a58b5cd095a3bb Author: Ladebeze66 Date: Tue Dec 12 17:32:54 2023 +0100 minishell diff --git a/Makefile b/Makefile new file mode 100755 index 0000000..5c366d6 --- /dev/null +++ b/Makefile @@ -0,0 +1,124 @@ +# **************************************************************************** # +# # +# ::: :::::::: # +# Makefile :+: :+: :+: # +# +:+ +:+ +:+ # +# By: fgras-ca +#+ +:+ +#+ # +# +#+#+#+#+#+ +#+ # +# Created: 2023/11/07 16:09:37 by fgras-ca #+# #+# # +# Updated: 2023/12/09 17:20:03 by fgras-ca ### ########.fr # +# # +# **************************************************************************** # + +RST = \033[0m +GRAY = \033[0;90m +RED = \033[0;91m +GREEN = \033[0;92m +YELLOW = \033[0;93m +BLUE = \033[0;94m +MAGENTA = \033[0;95m +CYAN = \033[0;96m +WHITE = \033[0;97m +ORANGE = \033[38;5;214m +# Nom du binaire à produire +NAME = minishell +LIBFT = libft.a + +# Liste des fichiers sources +SRCS = prompt/history.c \ + prompt/prompt.c \ + prompt/main.c \ + utils/utils.c \ + builtins/builtins.c \ + extern/extern.c \ + extern/extern_utils.c \ + builtins/export.c \ + builtins/export_utils.c \ + builtins/echo.c \ + builtins/unset.c \ + builtins/env.c \ + builtins/builtins_utils.c \ + signal/ctrl.c \ + tokenize/tokenize_symbol.c \ + tokenize/tokenize_utils.c \ + tokenize/tokenize.c \ + prompt/init_shell.c \ + parsing/parse_error.c \ + parsing/redirection_utils.c \ + parsing/variable_utils.c \ + parsing/parse_utils.c \ + parsing/herodoc.c \ + parsing/variable.c \ + command/command_array.c \ + command/command_utils.c \ + parsing/parse.c \ + command/command.c \ + tokenize/quotes.c \ + parsing/parse_redirections.c \ + parsing/redirection.c \ + parsing/pipe_utils.c \ + parsing/pipe.c \ + parsing/tree.c \ + builtins/export_env.c \ + + # Ajoutez ici les autres fichiers .c + +SRC_DIR_LIBFT = libft/ + +SRC_LIBFT = $(addprefix $(SRC_DIR_LIBFT), $(LIBFT)) + +# Liste des fichiers objets correspondants aux fichiers sources +OBJS = $(SRCS:.c=.o) + +# Compilateur +CC = gcc + +# Flags de compilation +CFLAGS = -Wall -Wextra -Werror + +# Règle par défaut +all: $(NAME) + +# Règle pour créer le binaire +$(NAME): $(OBJS) + @echo "$(RED)Loading Libft...$(RST)" + @make -C libft + @echo "$(GREEN)Libft...Done. $(RST)" + @echo "$(RED)Compilation minishell... $(RST)" + @$(CC) $(CFLAGS) $(OBJS) $(SRC_LIBFT) -o $(NAME) -lreadline -g + @echo "$(GREEN)Compilation complete. $(ORANGE)Type "./minishell" for execute the program!!$(RST)" + @echo "\n$(RED)# Ⓛⓐⓓⓔⓑⓔⓩⓔ ⓐⓝⓓ Ⓒⓥⓤ #$(RST)\n" + +# Règle pour créer les fichiers objets à partir des fichiers sources +%.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ + +# Règle pour nettoyer les fichiers objets +clean: + @echo "$(RED)Cleaning Libft... $(RST)" + @make -C libft clean + @echo "$(GREEN)Libft cleaned!! $(RST)" + @echo "$(RED)Deleating files objects... $(RST)" + rm -f $(OBJS) + @echo "$(GREEN)files deleted!! $(RST)" + @echo "\n$(RED)# Ⓛⓐⓓⓔⓑⓔⓩⓔ ⓐⓝⓓ Ⓒⓥⓤ #$(RST)\n" + +# Règle pour nettoyer les fichiers objets et le binaire +fclean: clean + @echo "$(RED)fclean Libft... $(RST)" + @make -C libft fclean + @echo "$(GREEN)Libft cleaned!! $(RST)" + @echo "$(RED)Delete program name... $(RST)" + rm -f $(NAME) + @echo "$(GREEN)File program deleted!! $(RST)" + @echo "\n$(RED)# Ⓛⓐⓓⓔⓑⓔⓩⓔ ⓐⓝⓓ Ⓒⓥⓤ #$(RST)\n" + +# Règle pour recompiler le projet entièrement +re: fclean all + +# Règle pour exécuter les tests +test: re + ./$(NAME) + +# Empêcher make d'être confus avec un fichier nommé comme une règle +.PHONY: all clean fclean re test diff --git a/builtins/builtins.c b/builtins/builtins.c new file mode 100755 index 0000000..f443792 --- /dev/null +++ b/builtins/builtins.c @@ -0,0 +1,116 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* builtins.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/11/12 11:51:11 by fgras-ca #+# #+# */ +/* Updated: 2023/12/09 14:06:48 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +int builtin_cd(char **args, t_minishell *shell) +{ + (void)shell; + if (args[1] == NULL) + { + write(2, RED"minishell: expected argument to \"cd\"\n"RST, 44); + } + else + { + if (chdir(args[1]) != 0) + { + perror(RED"minishell"RST); + } + } + return (0); +} + +int builtin_exit(char **args, t_minishell *shell) +{ + long exit_code; + char *endptr; + char *error_message; + + (void)shell; + if (args[1]) + { + errno = 0; + exit_code = strtol(args[1], &endptr, 10); + if ((errno == ERANGE && (exit_code == LONG_MAX + || exit_code == LONG_MIN)) || (errno != 0 && exit_code == 0) + || (*endptr != '\0') + || (exit_code < 0 || exit_code > 255)) + { + error_message = "bash: exit: "; + write(STDERR_FILENO, error_message, strlen(error_message)); + write(STDERR_FILENO, args[1], strlen(args[1])); + error_message = ": numeric argument required\n"; + write(STDERR_FILENO, error_message, strlen(error_message)); + return (1); + } + exit((int)exit_code); + } + exit(0); +} + +int builtin_pwd(char **args, t_minishell *shell) +{ + char cwd[1024]; + + (void)shell; + (void)args; + if (getcwd(cwd, sizeof(cwd)) != NULL) + { + printf("%s\n", cwd); + } + else + { + perror(RED"minishell"RST); + } + return (0); +} + +int num_builtins(t_minishell *shell) +{ + int count; + + count = 0; + while (shell->builtin_str[count]) + { + count++; + } + return (count); +} + +int execute_builtin(char **args, t_minishell *shell) +{ + int i; + int exit_status; + + if (!args || !shell || !shell->builtin_str || !shell->builtin_func) + return (-1); + if (!args[0]) + { + write(2, RED"Command not found: No such file or directory\n", 52); + return (-1); + } + i = 0; + while (i < num_builtins(shell)) + { + if (shell->builtin_str[i] && ft_strcmp(args[0], + shell->builtin_str[i]) == 0) + { + if (shell->builtin_func[i]) + { + exit_status = (*shell->builtin_func[i])(args, shell); + return (exit_status); + } + } + i++; + } + return (-1); +} diff --git a/builtins/builtins_utils.c b/builtins/builtins_utils.c new file mode 100755 index 0000000..1dbb8a5 --- /dev/null +++ b/builtins/builtins_utils.c @@ -0,0 +1,48 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* builtins_utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/11/27 20:33:11 by fgras-ca #+# #+# */ +/* Updated: 2023/12/08 23:02:49 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +char *extract_name(char *env_entry) +{ + int len; + char *name; + + len = 0; + while (env_entry[len] && env_entry[len] != '=') + len++; + name = malloc(len + 1); + if (!name) + return (NULL); + ft_strncpy(name, env_entry, len); + name[len] = '\0'; + return (name); +} + +char *extract_value(char *env_entry) +{ + int i; + char *value; + + i = 0; + while (env_entry[i] && env_entry[i] != '=') + i++; + if (!env_entry[i]) + return (NULL); + value = ft_strdup(&env_entry[i + 1]); + return (value); +} + +int builtin_echo_wrapper(char **args, t_minishell *shell) +{ + return (builtin_echo(args, shell, STDOUT_FILENO)); +} diff --git a/builtins/echo.c b/builtins/echo.c new file mode 100755 index 0000000..bb81571 --- /dev/null +++ b/builtins/echo.c @@ -0,0 +1,58 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* echo.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/11/11 18:27:30 by fgras-ca #+# #+# */ +/* Updated: 2023/12/09 18:57:20 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +static int check_option(char *s) +{ + int i; + + i = 1; + if (s[0] != '-') + return (0); + while (s[i]) + { + if (s[i] != 'n') + return (0); + i++; + } + return (1); +} + +int builtin_echo(char **args, t_minishell *shell, int fd) +{ + int i; + int newline; + char *output; + + i = 1; + newline = 1; + (void)shell; + if (args[i] != NULL && check_option(args[i])) + { + newline = 0; + i++; + } + while (args[i] != NULL) + { + output = args[i]; + write(fd, output, ft_strlen(output)); + if (args[i + 1] != NULL) + { + write(fd, " ", 1); + } + i++; + } + if (newline) + write(fd, "\n", 1); + return (0); +} diff --git a/builtins/env.c b/builtins/env.c new file mode 100755 index 0000000..c541ba6 --- /dev/null +++ b/builtins/env.c @@ -0,0 +1,29 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* env.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/11/15 17:36:35 by fgras-ca #+# #+# */ +/* Updated: 2023/12/07 12:10:09 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +int builtin_env(char **args, t_minishell *shell) +{ + int i; + char *env_var; + + (void)args; + i = 0; + while (shell->environ[i]) + { + env_var = shell->environ[i]; + printf("%s\n", env_var); + i++; + } + return (0); +} diff --git a/builtins/export.c b/builtins/export.c new file mode 100755 index 0000000..859a0a9 --- /dev/null +++ b/builtins/export.c @@ -0,0 +1,65 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* export.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/11/11 18:20:32 by fgras-ca #+# #+# */ +/* Updated: 2023/12/07 12:11:19 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +static void print_env(char **env, int env_size) +{ + int i; + char *name; + char *value; + + i = 0; + while (i < env_size) + { + name = extract_name(env[i]); + value = extract_value(env[i]); + if (value) + { + printf("declare -x %s=\"%s\"\n", name, value); + free(value); + } + else + { + printf("declare -x %s\n", name); + } + free(name); + i++; + } +} + +static void print_sorted_env(t_minishell *shell) +{ + int env_size; + char **sorted_env; + + env_size = count_env_vars(shell->environ); + sorted_env = copy_env(shell->environ, env_size); + if (!sorted_env) + return ; + sort_env(sorted_env, env_size); + print_env(sorted_env, env_size); + free(sorted_env); +} + +int builtin_export(char **args, t_minishell *shell) +{ + if (args[1] == NULL) + { + print_sorted_env(shell); + return (0); + } + else + { + return (export_set_env(args, shell)); + } +} diff --git a/builtins/export_env.c b/builtins/export_env.c new file mode 100755 index 0000000..5ce4274 --- /dev/null +++ b/builtins/export_env.c @@ -0,0 +1,66 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* export_env.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/12/01 10:49:41 by fgras-ca #+# #+# */ +/* Updated: 2023/12/07 12:19:27 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +int count_env_vars(char **environ) +{ + int count; + + count = 0; + while (environ[count]) + count++; + return (count); +} + +char **copy_env(char **environ, int env_size) +{ + char **env_copy; + int i; + + env_copy = malloc((env_size + 1) * sizeof(char *)); + if (!env_copy) + return (NULL); + i = 0; + while (i < env_size) + { + env_copy[i] = environ[i]; + i++; + } + env_copy[env_size] = NULL; + return (env_copy); +} + +void sort_env(char **env, int env_size) +{ + int sorted; + int i; + char *temp; + + sorted = 0; + while (!sorted) + { + sorted = 1; + i = 0; + while (i < env_size - 1) + { + if (strcmp(env[i], env[i + 1]) > 0) + { + temp = env[i]; + env[i] = env[i + 1]; + env[i + 1] = temp; + sorted = 0; + } + i++; + } + } +} diff --git a/builtins/export_utils.c b/builtins/export_utils.c new file mode 100755 index 0000000..9f3e974 --- /dev/null +++ b/builtins/export_utils.c @@ -0,0 +1,102 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* export_utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/11/15 18:26:09 by fgras-ca #+# #+# */ +/* Updated: 2023/12/09 15:01:53 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +static char *create_env_entry(char **args) +{ + char *new_env_entry; + char *name; + char *value; + + name = ft_strtok(args[1], "="); + value = ft_strtok(NULL, ""); + if (name == NULL || value == NULL) + { + write(2, RED"minishell: invalid format for export. " + "Use NAME=\"value\".\n"RST, 63); + return (NULL); + } + new_env_entry = malloc(strlen(name) + strlen(value) + 2); + if (!new_env_entry) + { + exit(EXIT_FAILURE); + } + ft_strcpy(new_env_entry, name); + ft_strcat(new_env_entry, "="); + ft_strcat(new_env_entry, value); + return (new_env_entry); +} + +int add_new_env_entry(t_minishell *shell, char *new_env_entry) +{ + int env_size; + size_t oldsize; + + env_size = 0; + oldsize = 0; + while (shell->environ[env_size] != NULL) + { + env_size++; + } + oldsize = (env_size + 1) * sizeof(char *); + shell->environ = ft_reallocarray(shell->environ, env_size + 2, + sizeof(char *), oldsize); + if (!shell->environ) + { + perror(RED"minishell: error reallocating environment"RST); + free(new_env_entry); + return (1); + } + shell->environ[env_size] = new_env_entry; + shell->environ[env_size + 1] = NULL; + return (0); +} + +int replace_env_entry(t_minishell *shell, char *new_env_entry) +{ + int i; + size_t name_length; + + i = 0; + name_length = ft_strchr(new_env_entry, '=') - new_env_entry; + while (shell->environ[i] != NULL) + { + if (ft_strncmp(shell->environ[i], new_env_entry, name_length) == 0) + { + free(shell->environ[i]); + shell->environ[i] = new_env_entry; + return (1); + } + i++; + } + return (0); +} + +static int update_env(t_minishell *shell, char *new_env_entry) +{ + if (replace_env_entry(shell, new_env_entry) == 0) + { + return (add_new_env_entry(shell, new_env_entry)); + } + return (0); +} + +int export_set_env(char **args, t_minishell *shell) +{ + char *new_env_entry; + + new_env_entry = create_env_entry(args); + if (new_env_entry == NULL) + return (0); + return (update_env(shell, new_env_entry)); +} diff --git a/builtins/unset.c b/builtins/unset.c new file mode 100755 index 0000000..e9929ef --- /dev/null +++ b/builtins/unset.c @@ -0,0 +1,42 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* unset.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/11/14 21:15:04 by fgras-ca #+# #+# */ +/* Updated: 2023/12/07 12:10:47 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +int builtin_unset(char **args, t_minishell *shell) +{ + int i; + int j; + + i = 0; + if (args[1] == NULL) + { + write(2, RED"minishell: expected argument to \"unset\"\n", 48); + return (1); + } + while (shell->environ[i] != NULL) + { + if (ft_strncmp(shell->environ[i], args[1], ft_strlen(args[1])) + == 0 && shell->environ[i][ft_strlen(args[1])] == '=') + { + j = i; + while (shell->environ[j] != NULL) + { + shell->environ[j] = shell->environ[j + 1]; + j++; + } + break ; + } + i++; + } + return (0); +} diff --git a/command/command.c b/command/command.c new file mode 100755 index 0000000..0730e52 --- /dev/null +++ b/command/command.c @@ -0,0 +1,83 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* command.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/11/29 21:21:23 by fgras-ca #+# #+# */ +/* Updated: 2023/12/09 18:55:48 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +int execute_builtin_and_free(char **args, t_minishell *shell, int fd) +{ + int status; + + if (ft_strcmp(args[0], "echo") == 0) + { + status = builtin_echo(args, shell, fd); + } + else + { + status = execute_builtin(args, shell); + } + free_args_array(args); + shell->last_exit_status = status; + return (status); +} + +static int execute_external_and_free(char **args, t_minishell *shell) +{ + pid_t pid; + int status; + + status = 0; + pid = execute_external_command(args, shell->environ); + free_args_array(args); + if (pid > 0) + { + waitpid(pid, &status, WUNTRACED); + if (WIFEXITED(status)) + { + shell->last_exit_status = WEXITSTATUS(status); + } + } + else + { + shell->last_exit_status = 127; + } + return (status); +} + +static int process_command(t_command *command, t_minishell *shell, int fd) +{ + char **args; + int status; + + status = 0; + args = build_args_array(command); + if (args != NULL) + { + if (is_builtin_command(command->command, shell)) + { + status = execute_builtin_and_free(args, shell, fd); + } + else + { + status = execute_external_and_free(args, shell); + } + } + return (status); +} + +void execute_command(t_command *command, t_minishell *shell, int fd) +{ + if (command == NULL || command->command == NULL) + { + return ; + } + process_command(command, shell, fd); +} diff --git a/command/command_array.c b/command/command_array.c new file mode 100755 index 0000000..566d7b3 --- /dev/null +++ b/command/command_array.c @@ -0,0 +1,80 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* command_array.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/12/01 11:26:25 by fgras-ca #+# #+# */ +/* Updated: 2023/12/09 18:56:21 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +static char **allocate_args_array(t_command *command) +{ + char **args; + + args = malloc(sizeof(char *) * (command->arg_count + 2)); + if (!args) + { + return (NULL); + } + return (args); +} + +static int duplicate_command_arg(char **args, t_command *command, int i) +{ + args[i + 1] = ft_strdup(command->args[i]); + if (!args[i + 1]) + { + while (--i >= 0) + free(args[i + 1]); + free(args[0]); + free(args); + return (0); + } + return (1); +} + +char **build_args_array(t_command *command) +{ + char **args; + int i; + + args = allocate_args_array(command); + if (!args) + return (NULL); + args[0] = ft_strdup(command->command); + if (!args[0]) + { + free(args); + return (NULL); + } + i = 0; + while (i < command->arg_count) + { + if (!duplicate_command_arg(args, command, i)) + return (NULL); + i++; + } + args[command->arg_count + 1] = NULL; + return (args); +} + +void free_args_array(char **args) +{ + int i; + + i = 0; + if (args) + { + while (args[i] != NULL) + { + free(args[i]); + i++; + } + free(args); + } +} diff --git a/command/command_utils.c b/command/command_utils.c new file mode 100755 index 0000000..59ec78c --- /dev/null +++ b/command/command_utils.c @@ -0,0 +1,83 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* command_utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/12/01 11:03:59 by fgras-ca #+# #+# */ +/* Updated: 2023/12/10 12:21:17 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +void free_command(t_command *command) +{ + int i; + + if (!command) + return ; + free(command->command); + if (command->args) + { + i = 0; + while (i < command->arg_count) + { + free(command->args[i]); + i++; + } + free(command->args); + } +} + +void reset_command(t_command *command) +{ + if (!command) + return ; + free_command(command); + command->command = NULL; + command->args = NULL; + command->arg_count = 0; +} + +t_command *create_new_command(void) +{ + t_command *new_command; + + new_command = malloc(sizeof(t_command)); + if (new_command == NULL) + return (NULL); + new_command->command = NULL; + new_command->args = NULL; + new_command->arg_count = 0; + return (new_command); +} + +void add_token_to_command(t_command *command, char *token) +{ + char **new_args; + char *new_token; + + if (!token || *token == '\0' || !command) + return ; + new_token = ft_strdup(token); + if (!new_token) + return ; + if (command->command == NULL) + command->command = new_token; + else + { + new_args = ft_realloc(command->args, + sizeof(char *) * (command->arg_count + 2), + sizeof(char *) * command->arg_count); + if (!new_args) + { + free(new_token); + return ; + } + command->args = new_args; + command->args[command->arg_count++] = new_token; + command->args[command->arg_count] = NULL; + } +} diff --git a/en.subject.pdf b/en.subject.pdf new file mode 100644 index 0000000..6381683 --- /dev/null +++ b/en.subject.pdf @@ -0,0 +1,232 @@ + Minishell + + As beautiful as a shell + + Summary: + This project is about creating a simple shell. + + Yes, your own little bash. +You will learn a lot about processes and file descriptors. + + Version: 7.1 + Contents + +I Introduction 2 + +II Common Instructions 3 + +III Mandatory part 5 + +IV Bonus part 8 + +V Submission and peer-evaluation 9 + + 1 + Chapter I +Introduction + +The existence of shells is linked to the very existence of IT. + At the time, all developers agreed that communicating with a computer using aligned + +1/0 switches was seriously irritating. + It was only logical that they came up with the idea of creating a software to com- + +municate with a computer using interactive lines of commands in a language somewhat +close to the human language. + + Thanks to Minishell, you’ll be able to travel through time and come back to problems +people faced when Windows didn’t exist. + + 2 + Chapter II + +Common Instructions + + • Your project must be written in C. + + • Your project must be written in accordance with the Norm. If you have bonus + files/functions, they are included in the norm check and you will receive a 0 if there + is a norm error inside. + + • Your functions should not quit unexpectedly (segmentation fault, bus error, double + free, etc) apart from undefined behaviors. If this happens, your project will be + considered non functional and will receive a 0 during the evaluation. + + • All heap allocated memory space must be properly freed when necessary. No leaks + will be tolerated. + + • If the subject requires it, you must submit a Makefile which will compile your + source files to the required output with the flags -Wall, -Wextra and -Werror, use + cc, and your Makefile must not relink. + + • Your Makefile must at least contain the rules $(NAME), all, clean, fclean and + re. + + • To turn in bonuses to your project, you must include a rule bonus to your Makefile, + which will add all the various headers, librairies or functions that are forbidden on + the main part of the project. Bonuses must be in a different file _bonus.{c/h} if + the subject does not specify anything else. Mandatory and bonus part evaluation + is done separately. + + • If your project allows you to use your libft, you must copy its sources and its + associated Makefile in a libft folder with its associated Makefile. Your project’s + Makefile must compile the library by using its Makefile, then compile the project. + + • We encourage you to create test programs for your project even though this work + won’t have to be submitted and won’t be graded. It will give you a chance + to easily test your work and your peers’ work. You will find those tests especially + useful during your defence. Indeed, during defence, you are free to use your tests + and/or the tests of the peer you are evaluating. + + • Submit your work to your assigned git repository. Only the work in the git reposi- + tory will be graded. If Deepthought is assigned to grade your work, it will be done + + 3 + Minishell As beautiful as a shell + +after your peer-evaluations. If an error happens in any section of your work during +Deepthought’s grading, the evaluation will stop. + + 4 + Chapter III +Mandatory part + +Program name minishell +Turn in files Makefile, *.h, *.c +Makefile NAME, all, clean, fclean, re +Arguments +External functs. readline, rl_clear_history, rl_on_new_line, + rl_replace_line, rl_redisplay, add_history, +Libft authorized printf, malloc, free, write, access, open, read, +Description close, fork, wait, waitpid, wait3, wait4, signal, + sigaction, sigemptyset, sigaddset, kill, exit, + getcwd, chdir, stat, lstat, fstat, unlink, execve, + dup, dup2, pipe, opendir, readdir, closedir, + strerror, perror, isatty, ttyname, ttyslot, ioctl, + getenv, tcsetattr, tcgetattr, tgetent, tgetflag, + tgetnum, tgetstr, tgoto, tputs + Yes + Write a shell + +Your shell should: + +• Display a prompt when waiting for a new command. + +• Have a working history. + +• Search and launch the right executable (based on the PATH variable or using a + relative or an absolute path). + +• Avoid using more than one global variable to indicate a received signal. Consider + the implications: this approach ensures that your signal handler will not access your + main data structures. + +Be careful. This global variable cannot provide any other +information or data access than the number of a received signal. +Therefore, using "norm" type structures in the global scope is +forbidden. + + 5 + Minishell As beautiful as a shell + +• Not interpret unclosed quotes or special characters which are not required by the + subject such as \ (backslash) or ; (semicolon). + +• Handle ’ (single quote) which should prevent the shell from interpreting the meta- + characters in the quoted sequence. + +• Handle " (double quote) which should prevent the shell from interpreting the meta- + characters in the quoted sequence except for $ (dollar sign). + +• Implement redirections: + + ◦ < should redirect input. + ◦ > should redirect output. + ◦ << should be given a delimiter, then read the input until a line containing the + + delimiter is seen. However, it doesn’t have to update the history! + ◦ >> should redirect output in append mode. + +• Implement pipes (| character). The output of each command in the pipeline is + connected to the input of the next command via a pipe. + +• Handle environment variables ($ followed by a sequence of characters) which + should expand to their values. + +• Handle $? which should expand to the exit status of the most recently executed + foreground pipeline. + +• Handle ctrl-C, ctrl-D and ctrl-\ which should behave like in bash. +• In interactive mode: + + ◦ ctrl-C displays a new prompt on a new line. + ◦ ctrl-D exits the shell. + ◦ ctrl-\ does nothing. + +• Your shell must implement the following builtins: + + ◦ echo with option -n + ◦ cd with only a relative or absolute path + ◦ pwd with no options + ◦ export with no options + ◦ unset with no options + ◦ env with no options or arguments + ◦ exit with no options + + 6 + Minishell As beautiful as a shell + + The readline() function can cause memory leaks. You don’t have to fix them. But +that doesn’t mean your own code, yes the code you wrote, can have memory +leaks. + + You should limit yourself to the subject description. Anything that + is not asked is not required. + If you have any doubt about a requirement, take bash as a reference. + + 7 + Chapter IV +Bonus part + +Your program has to implement: + • && and || with parenthesis for priorities. + • Wildcards * should work for the current working directory. + + The bonus part will only be assessed if the mandatory part is + PERFECT. Perfect means the mandatory part has been integrally done + and works without malfunctioning. If you have not passed ALL the + mandatory requirements, your bonus part will not be evaluated at all. + + 8 + Chapter V + +Submission and peer-evaluation + +Turn in your assignment in your Git repository as usual. Only the work inside your +repository will be evaluated during the defense. Don’t hesitate to double check the +names of your files to ensure they are correct. + + M LQ* d z Ok v P + + : )? e Q 6 u nk] R * + +f *q lV - O , ?ZP + + 7 c 1V H + + e 9 () 8 + + U + + ’> D s / w + + ; E ’ >M + + q < > + + zb H ( 3 + l 6 + X 0g E + + 9 + diff --git a/extern/extern.c b/extern/extern.c new file mode 100755 index 0000000..b0f7b77 --- /dev/null +++ b/extern/extern.c @@ -0,0 +1,56 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* extern.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/11/11 17:45:14 by fgras-ca #+# #+# */ +/* Updated: 2023/12/07 12:23:50 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +pid_t create_process(char *path, char **args, char **environ) +{ + pid_t pid; + + pid = fork(); + if (pid == 0) + { + execve(path, args, environ); + perror(RED"Command execution failed"RST); + exit(EXIT_FAILURE); + } + else if (pid < 0) + { + perror(RED"Fork failed"RST); + } + return (pid); +} + +pid_t execute_external_command(char **args, char **environ) +{ + pid_t pid; + char *path; + + pid = -1; + if (!args || !args[0]) + return (-1); + path = find_executable(args[0], environ); + if (!path) + { + write(2, args[0], ft_strlen(args[0])); + write(2, ": ", 2); + perror(RED "Command not found" RST); + return (-1); + } + pid = create_process(path, args, environ); + if (pid < 0) + { + perror(RED"Fork failed"RST); + } + free(path); + return (pid); +} diff --git a/extern/extern_utils.c b/extern/extern_utils.c new file mode 100755 index 0000000..697720b --- /dev/null +++ b/extern/extern_utils.c @@ -0,0 +1,87 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* extern_utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/11/27 19:48:07 by fgras-ca #+# #+# */ +/* Updated: 2023/12/07 12:24:31 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +static char *check_relative_path(const char *cmd) +{ + if (cmd == NULL) + return (NULL); + if (ft_strncmp(cmd, "./", 2) == 0 + || ft_strncmp(cmd, "../", 3) == 0 || cmd[0] == '/') + { + if (access(cmd, X_OK) == 0) + return (ft_strdup(cmd)); + } + return (NULL); +} + +static char *build_full_path(const char *token, const char *cmd) +{ + char *temp; + + if (cmd == NULL) + return (NULL); + temp = malloc(ft_strlen(token) + ft_strlen(cmd) + 2); + if (temp == NULL) + return (NULL); + ft_strcpy(temp, token); + ft_strcat(temp, "/"); + ft_strcat(temp, cmd); + return (temp); +} + +static char *search_path(char *path, const char *cmd) +{ + char *path_copy; + char *token; + char *temp; + char *full_path; + + if (cmd == NULL) + return (NULL); + full_path = NULL; + path_copy = ft_strdup(path); + token = ft_strtok(path_copy, ":"); + while (token != NULL) + { + temp = build_full_path(token, cmd); + if (temp && access(temp, X_OK) == 0) + { + full_path = ft_strdup(temp); + free(temp); + break ; + } + free(temp); + token = ft_strtok(NULL, ":"); + } + free(path_copy); + return (full_path); +} + +char *find_executable(const char *cmd, char **environ) +{ + char *path; + char *relative_path_check; + char *full_path; + + if (cmd == NULL) + return (NULL); + relative_path_check = check_relative_path(cmd); + if (relative_path_check != NULL) + return (relative_path_check); + path = get_env_value("PATH", environ); + if (!path || ft_strlen(path) == 0) + return (NULL); + full_path = search_path(path, cmd); + return (full_path); +} diff --git a/libft/Makefile b/libft/Makefile new file mode 100755 index 0000000..0aa9d16 --- /dev/null +++ b/libft/Makefile @@ -0,0 +1,111 @@ +# **************************************************************************** # +# # +# ::: :::::::: # +# Makefile :+: :+: :+: # +# +:+ +:+ +:+ # +# By: fgras-ca +#+ +:+ +#+ # +# +#+#+#+#+#+ +#+ # +# Created: 2023/02/06 12:19:21 by fgras-ca #+# #+# # +# Updated: 2023/12/07 11:25:50 by fgras-ca ### ########.fr # +# # +# **************************************************************************** # + +RST = \033[0m +GRAY = \033[0;90m +RED = \033[0;91m +GREEN = \033[0;92m +YELLOW = \033[0;93m +BLUE = \033[0;94m +MAGENTA = \033[0;95m +CYAN = \033[0;96m +WHITE = \033[0;97m +ORANGE = \033[38;5;214m +NAME = libft.a + +SOURCES = ft_atoi.c \ + ft_isalpha.c \ + ft_memchr.c \ + ft_memset.c \ + ft_strlcat.c \ + ft_strnstr.c \ + ft_toupper.c \ + ft_bzero.c \ + ft_isascii.c \ + ft_memcmp.c \ + ft_strchr.c \ + ft_strlcpy.c \ + ft_strrchr.c \ + ft_calloc.c \ + ft_isdigit.c \ + ft_memcpy.c \ + ft_strdup.c \ + ft_strlen.c \ + ft_substr.c \ + ft_isalnum.c \ + ft_isprint.c \ + ft_memmove.c \ + ft_strjoin.c \ + ft_strncmp.c \ + ft_tolower.c\ + ft_strtrim.c \ + ft_putchar_fd.c \ + ft_putstr_fd.c \ + ft_putendl_fd.c \ + ft_putnbr_fd.c \ + ft_strmapi.c \ + ft_striteri.c \ + ft_split.c \ + ft_itoa.c \ + ft_strcmp.c \ + ft_strstr.c \ + ft_reallocarray.c \ + ft_strcat.c \ + ft_strcpy.c \ + ft_realloc.c \ + ft_strncpy.c \ + ft_strtol.c \ + ft_strtok.c \ + +SRCBONUS = ft_lstnew.c \ + ft_lstadd_front.c \ + ft_lstsize.c \ + ft_lstlast.c \ + ft_lstadd_back.c \ + ft_lstdelone.c \ + ft_lstclear.c \ + ft_lstiter.c \ + ft_lstiter.c \ + ft_lstmap.c \ + + +OBJECTS = $(SOURCES:.c=.o) + +BONUS_OBJ = $(SRCBONUS:.c=.o) + +CC = gcc + +RM = rm -f + +CFLAGS = -Wall -Werror -Wextra + +all: $(NAME) + +$(NAME): $(OBJECTS) + @ar rcs $(NAME) $(OBJECTS) + +bonus: $(OBJECTS) $(BONUS_OBJ) + @ar rcs $(NAME) $(OBJECTS) $(BONUS_OBJ) + +main.o: + gcc -c main.c + +ccmainlib: + $(CC) $(CFLAGS) main.c -L -lft + +clean: + @$(RM) $(OBJECTS) $(BONUS_OBJ) + +fclean: clean + @$(RM) $(NAME) + +re: fclean all diff --git a/libft/ft_atoi.c b/libft/ft_atoi.c new file mode 100755 index 0000000..5756d38 --- /dev/null +++ b/libft/ft_atoi.c @@ -0,0 +1,38 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_atoi.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/11 16:16:54 by fgras-ca #+# #+# */ +/* Updated: 2023/02/21 09:57:55 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +int ft_atoi(const char *nptr) +{ + int i; + int sign; + int res; + + i = 0; + sign = 1; + res = 0; + while (nptr[i] == 32 || (nptr[i] >= 9 && nptr[i] <= 13)) + i++; + if (nptr[i] == '-' || nptr[i] == '+') + { + if (nptr[i] == '-') + sign = - (1); + i++; + } + while (nptr[i] >= 48 && nptr[i] <= 57) + { + res = res * 10 + nptr[i] - 48; + i++; + } + return (res * sign); +} diff --git a/libft/ft_bzero.c b/libft/ft_bzero.c new file mode 100755 index 0000000..d032508 --- /dev/null +++ b/libft/ft_bzero.c @@ -0,0 +1,25 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_bzero.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/04 11:37:30 by fgras-ca #+# #+# */ +/* Updated: 2023/02/20 16:07:19 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void ft_bzero(void *ptr, size_t len) +{ + size_t i; + + i = 0; + while (i < len) + { + *(char *)(ptr + i) = 0; + i++; + } +} diff --git a/libft/ft_calloc.c b/libft/ft_calloc.c new file mode 100755 index 0000000..8858bcf --- /dev/null +++ b/libft/ft_calloc.c @@ -0,0 +1,28 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_calloc.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/11 17:47:38 by fgras-ca #+# #+# */ +/* Updated: 2023/02/21 10:45:58 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void *ft_calloc(size_t nmemb, size_t size) +{ + void *ptr; + + if (!nmemb || !size) + return (malloc(0)); + if ((nmemb * size) / size != nmemb) + return (NULL); + ptr = malloc(size * nmemb); + if (!ptr) + return (0); + ft_bzero(ptr, size * nmemb); + return (ptr); +} diff --git a/libft/ft_isalnum.c b/libft/ft_isalnum.c new file mode 100755 index 0000000..1f065f3 --- /dev/null +++ b/libft/ft_isalnum.c @@ -0,0 +1,21 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_isalnum.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/01 16:21:11 by fgras-ca #+# #+# */ +/* Updated: 2023/02/01 16:24:23 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +int ft_isalnum(int c) +{ + if ((c >= 65 && c <= 90) || (c >= 97 && c <= 122) || (c >= 48 && c <= 57)) + return (1); + else + return (0); +} diff --git a/libft/ft_isalpha.c b/libft/ft_isalpha.c new file mode 100755 index 0000000..3ff8fc5 --- /dev/null +++ b/libft/ft_isalpha.c @@ -0,0 +1,21 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_isalpha.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/01 13:36:34 by fgras-ca #+# #+# */ +/* Updated: 2023/02/01 13:58:21 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +int ft_isalpha(int c) +{ + if ((c >= 65 && c <= 90) || (c >= 97 && c <= 122)) + return (1); + else + return (0); +} diff --git a/libft/ft_isascii.c b/libft/ft_isascii.c new file mode 100755 index 0000000..508aa16 --- /dev/null +++ b/libft/ft_isascii.c @@ -0,0 +1,20 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_isascii.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/01 16:40:31 by fgras-ca #+# #+# */ +/* Updated: 2023/11/14 17:07:04 by fgras-ca ### ########.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 100755 index 0000000..30eff04 --- /dev/null +++ b/libft/ft_isdigit.c @@ -0,0 +1,21 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_isdigit.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/01 14:46:59 by fgras-ca #+# #+# */ +/* Updated: 2023/02/01 15:55:00 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +int ft_isdigit(int c) +{ + if (c >= 48 && c <= 57) + return (1); + else + return (0); +} diff --git a/libft/ft_isprint.c b/libft/ft_isprint.c new file mode 100755 index 0000000..2f6097d --- /dev/null +++ b/libft/ft_isprint.c @@ -0,0 +1,20 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_isprint.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/03 12:43:03 by fgras-ca #+# #+# */ +/* Updated: 2023/02/03 13:25:31 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +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 100755 index 0000000..b8f8a48 --- /dev/null +++ b/libft/ft_itoa.c @@ -0,0 +1,56 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_itoa.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/17 15:53:35 by fgras-ca #+# #+# */ +/* Updated: 2023/02/21 10:21:07 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +static size_t ft_len_nb(int nb) +{ + int len; + + len = 0; + if (nb <= 0) + len++; + while (nb) + { + len++; + nb = nb / 10; + } + return (len); +} + +char *ft_itoa(int n) +{ + int len; + char *str; + long nb; + + len = ft_len_nb(n); + nb = n; + str = malloc(sizeof(char) * len +1); + if (!str) + return (0); + if (nb < 0) + { + str[0] = '-'; + nb = -nb; + } + if (nb == 0) + str[0] = '0'; + str[len--] = '\0'; + while (nb) + { + str[len] = nb % 10 + '0'; + len--; + nb = nb / 10; + } + return (str); +} diff --git a/libft/ft_lstadd_back.c b/libft/ft_lstadd_back.c new file mode 100755 index 0000000..3615437 --- /dev/null +++ b/libft/ft_lstadd_back.c @@ -0,0 +1,29 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_lstadd_back.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/23 18:08:00 by fgras-ca #+# #+# */ +/* Updated: 2023/02/23 18:15:14 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void ft_lstadd_back(t_list **lst, t_list *new) +{ + t_list *temp; + + if (new && lst) + { + if (*lst) + { + temp = ft_lstlast(*lst); + temp->next = new; + } + else + *lst = new; + } +} diff --git a/libft/ft_lstadd_front.c b/libft/ft_lstadd_front.c new file mode 100755 index 0000000..01305fe --- /dev/null +++ b/libft/ft_lstadd_front.c @@ -0,0 +1,22 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_lstadd_front.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/22 18:06:54 by fgras-ca #+# #+# */ +/* Updated: 2023/11/14 17:06:52 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void ft_lstadd_front(t_list **lst, t_list *new) +{ + if (new) + { + new->next = *lst; + *lst = new; + } +} diff --git a/libft/ft_lstclear.c b/libft/ft_lstclear.c new file mode 100755 index 0000000..2367922 --- /dev/null +++ b/libft/ft_lstclear.c @@ -0,0 +1,25 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_lstclear.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/23 18:19:42 by fgras-ca #+# #+# */ +/* Updated: 2023/02/23 18:22:17 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void ft_lstclear(t_list **lst, void (*del)(void*)) +{ + t_list *temp; + + while (*lst && lst) + { + temp = (*lst)->next; + ft_lstdelone(*lst, (*del)); + *lst = temp; + } +} diff --git a/libft/ft_lstdelone.c b/libft/ft_lstdelone.c new file mode 100755 index 0000000..07b9774 --- /dev/null +++ b/libft/ft_lstdelone.c @@ -0,0 +1,21 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_lstdelone.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/23 18:17:06 by fgras-ca #+# #+# */ +/* Updated: 2023/02/23 18:33:01 by fgras-ca ### ########.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.c b/libft/ft_lstiter.c new file mode 100755 index 0000000..efed585 --- /dev/null +++ b/libft/ft_lstiter.c @@ -0,0 +1,24 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_lstiter.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/23 18:22:52 by fgras-ca #+# #+# */ +/* Updated: 2023/02/23 18:24:51 by fgras-ca ### ########.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.c b/libft/ft_lstlast.c new file mode 100755 index 0000000..e6279bb --- /dev/null +++ b/libft/ft_lstlast.c @@ -0,0 +1,24 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_lstlast.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/23 17:48:29 by fgras-ca #+# #+# */ +/* Updated: 2023/02/23 18:02:44 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +t_list *ft_lstlast(t_list *lst) +{ + while (lst) + { + if (lst->next == NULL) + return (lst); + lst = lst->next; + } + return (lst); +} diff --git a/libft/ft_lstmap.c b/libft/ft_lstmap.c new file mode 100755 index 0000000..eea1576 --- /dev/null +++ b/libft/ft_lstmap.c @@ -0,0 +1,35 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_lstmap.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/23 18:25:24 by fgras-ca #+# #+# */ +/* Updated: 2023/02/23 18:29:44 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +t_list *ft_lstmap(t_list *lst, void *(*f)(void *), void (*del)(void *)) +{ + t_list *tmp; + t_list *res; + + if (!lst || !f) + return (NULL); + res = 0; + while (lst) + { + tmp = ft_lstnew((*f)(lst->content)); + if (!tmp) + { + ft_lstclear(&res, del); + return (NULL); + } + ft_lstadd_back(&res, tmp); + lst = lst->next; + } + return (res); +} diff --git a/libft/ft_lstnew.c b/libft/ft_lstnew.c new file mode 100755 index 0000000..0ceaea4 --- /dev/null +++ b/libft/ft_lstnew.c @@ -0,0 +1,25 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_lstnew.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/22 17:09:25 by fgras-ca #+# #+# */ +/* Updated: 2023/11/14 17:06:38 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +t_list *ft_lstnew(void *content) +{ + t_list *new; + + new = malloc(sizeof(t_list)); + if (!new) + return (0); + new->content = content; + new->next = 0; + return (new); +} diff --git a/libft/ft_lstsize.c b/libft/ft_lstsize.c new file mode 100755 index 0000000..8c95558 --- /dev/null +++ b/libft/ft_lstsize.c @@ -0,0 +1,28 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_lstsize.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/23 17:17:36 by fgras-ca #+# #+# */ +/* Updated: 2023/11/14 17:06:24 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +int ft_lstsize(t_list *lst) +{ + int i; + t_list *tmp; + + tmp = lst; + i = 0; + while (tmp) + { + tmp = tmp->next; + i++; + } + return (i); +} diff --git a/libft/ft_memchr.c b/libft/ft_memchr.c new file mode 100755 index 0000000..34c95f7 --- /dev/null +++ b/libft/ft_memchr.c @@ -0,0 +1,27 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_memchr.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/10 13:42:10 by fgras-ca #+# #+# */ +/* Updated: 2023/02/14 13:03:28 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void *ft_memchr(const void *s, int c, size_t n) +{ + size_t i; + + i = 0; + while (i < n) + { + if (((unsigned char *)s)[i] == (unsigned char)c) + return ((void *)(s + i)); + i++; + } + return (0); +} diff --git a/libft/ft_memcmp.c b/libft/ft_memcmp.c new file mode 100755 index 0000000..ba77f19 --- /dev/null +++ b/libft/ft_memcmp.c @@ -0,0 +1,27 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_memcmp.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/10 14:45:56 by fgras-ca #+# #+# */ +/* Updated: 2023/11/14 17:18:05 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +int ft_memcmp(const void *s1, const void *s2, size_t n) +{ + size_t i; + + i = 0; + while (i < n) + { + if (((unsigned char *)s1)[i] != ((unsigned char *)s2)[i]) + return (((unsigned char *)s1)[i] - ((unsigned char *)s2)[i]); + i++; + } + return (0); +} diff --git a/libft/ft_memcpy.c b/libft/ft_memcpy.c new file mode 100755 index 0000000..5473b65 --- /dev/null +++ b/libft/ft_memcpy.c @@ -0,0 +1,32 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_memcpy.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/04 14:43:15 by fgras-ca #+# #+# */ +/* Updated: 2023/02/20 16:13:43 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void *ft_memcpy(void *dest, const void *src, size_t n) +{ + char *destmov; + char *srcmov; + size_t i; + + destmov = (char *)dest; + srcmov = (char *)src; + if (!dest && !src) + return (0); + i = 0; + while (i < n) + { + destmov[i] = srcmov[i]; + i++; + } + return (dest); +} diff --git a/libft/ft_memmove.c b/libft/ft_memmove.c new file mode 100755 index 0000000..c6d9588 --- /dev/null +++ b/libft/ft_memmove.c @@ -0,0 +1,42 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_memmove.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/07 11:11:49 by fgras-ca #+# #+# */ +/* Updated: 2023/02/07 16:04:25 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void *ft_memmove(void *dest, const void *src, size_t n) +{ + char *destmov; + char *srcmov; + size_t i; + + if (!dest && !src) + return (0); + destmov = (char *)dest; + srcmov = (char *)src; + i = 0; + if (destmov > srcmov) + { + while (n--) + { + destmov[n] = srcmov[n]; + } + } + else + { + while (n--) + { + destmov[i] = srcmov[i]; + i++; + } + } + return (destmov); +} diff --git a/libft/ft_memset.c b/libft/ft_memset.c new file mode 100755 index 0000000..2ad7299 --- /dev/null +++ b/libft/ft_memset.c @@ -0,0 +1,26 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_memset.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/03 15:49:51 by fgras-ca #+# #+# */ +/* Updated: 2023/11/14 17:07:29 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void *ft_memset(void *s, int c, size_t n) +{ + size_t i; + + i = 0; + while (i < n) + { + *(unsigned char *)(s + i) = (unsigned char)c; + i++; + } + return (s); +} diff --git a/libft/ft_putchar_fd.c b/libft/ft_putchar_fd.c new file mode 100755 index 0000000..b8a82d7 --- /dev/null +++ b/libft/ft_putchar_fd.c @@ -0,0 +1,18 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_putchar_fd.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/15 11:23:07 by fgras-ca #+# #+# */ +/* Updated: 2023/02/15 11:30:37 by fgras-ca ### ########.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 100755 index 0000000..9f65fcc --- /dev/null +++ b/libft/ft_putendl_fd.c @@ -0,0 +1,28 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_putendl_fd.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/15 13:33:49 by fgras-ca #+# #+# */ +/* Updated: 2023/02/21 10:19:05 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void ft_putendl_fd(char *s, int fd) +{ + int i; + + i = 0; + if (!s) + return ; + while (s[i]) + { + write(fd, &s[i], 1); + i++; + } + write(fd, "\n", 1); +} diff --git a/libft/ft_putnbr_fd.c b/libft/ft_putnbr_fd.c new file mode 100755 index 0000000..d71d21d --- /dev/null +++ b/libft/ft_putnbr_fd.c @@ -0,0 +1,36 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_putnbr_fd.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/15 13:53:25 by fgras-ca #+# #+# */ +/* Updated: 2023/02/15 14:00:06 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void ft_putnbr_fd(int n, int fd) +{ + if (n == -2147483648) + { + write(fd, "-2147483648", 11); + } + else if (n >= 0 && n < 10) + { + n += 48; + ft_putchar_fd(n, fd); + } + else if (n < 0) + { + ft_putchar_fd('-', fd); + ft_putnbr_fd((n * (-1)), fd); + } + else + { + ft_putnbr_fd(n / 10, fd); + ft_putnbr_fd(n % 10, fd); + } +} diff --git a/libft/ft_putstr_fd.c b/libft/ft_putstr_fd.c new file mode 100755 index 0000000..e266011 --- /dev/null +++ b/libft/ft_putstr_fd.c @@ -0,0 +1,27 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_putstr_fd.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/15 12:29:14 by fgras-ca #+# #+# */ +/* Updated: 2023/02/15 19:02:37 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void ft_putstr_fd(char *s, int fd) +{ + int i; + + i = 0; + if (!s || !fd) + return ; + while (s[i]) + { + write(fd, &s[i], 1); + i++; + } +} diff --git a/libft/ft_realloc.c b/libft/ft_realloc.c new file mode 100755 index 0000000..9fccdf1 --- /dev/null +++ b/libft/ft_realloc.c @@ -0,0 +1,35 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_realloc.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/11/15 16:31:35 by fgras-ca #+# #+# */ +/* Updated: 2023/12/10 13:59:12 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +void *ft_realloc(void *ptr, size_t newsize, size_t oldsize) +{ + char *newptr; + + if (ptr == NULL) + { + return (malloc(newsize)); + } + if (newsize <= oldsize) + { + return (ptr); + } + newptr = malloc(newsize); + if (newptr == NULL) + { + return (NULL); + } + ft_memcpy(newptr, ptr, oldsize); + free(ptr); + return (newptr); +} diff --git a/libft/ft_reallocarray.c b/libft/ft_reallocarray.c new file mode 100755 index 0000000..cc89e9a --- /dev/null +++ b/libft/ft_reallocarray.c @@ -0,0 +1,32 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_reallocarray.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/11/15 15:52:29 by fgras-ca #+# #+# */ +/* Updated: 2023/12/07 11:46:15 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +static size_t get_mul_no_overflow(void) +{ + return ((size_t)1 << (sizeof(size_t) * 4)); +} + +void *ft_reallocarray(void *optr, size_t nmemb, size_t size, size_t oldsize) +{ + size_t mul_no_overflow; + + mul_no_overflow = get_mul_no_overflow(); + if ((nmemb >= mul_no_overflow || size >= mul_no_overflow) + && nmemb > 0 && SIZE_MAX / nmemb < size) + { + errno = ENOMEM; + return (NULL); + } + return (ft_realloc(optr, nmemb * size, oldsize)); +} diff --git a/libft/ft_split.c b/libft/ft_split.c new file mode 100755 index 0000000..7e32a50 --- /dev/null +++ b/libft/ft_split.c @@ -0,0 +1,75 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_split.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/17 13:12:04 by fgras-ca #+# #+# */ +/* Updated: 2023/02/21 11:04:10 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +static int count_words(const char *s, char c) +{ + int count; + int trigger; + + count = 0; + trigger = 0; + while (*s) + { + if (*s != c && trigger == 0) + { + trigger = 1; + count++; + } + else if (*s == c) + trigger = 0; + s++; + } + return (count); +} + +static char *word_cpy(const char *s, int start, int end) +{ + char *word; + int i; + + i = 0; + word = malloc(sizeof(char) * (end - start + 1)); + while (start < end) + word[i++] = s[start++]; + word[i] = '\0'; + return (word); +} + +char **ft_split(char const *s, char c) +{ + size_t i; + size_t j; + int index; + char **split; + + split = malloc(sizeof(char *) * (count_words(s, c) + 1)); + if (!s || !split) + return (0); + i = 0; + j = 0; + index = -1; + while (i <= ft_strlen(s)) + { + if (s[i] != c && index < 0) + index = i; + else if ((s[i] == c || i == ft_strlen(s)) && index >= 0) + { + split[j++] = word_cpy(s, index, i); + index = -1; + } + i++; + } + split[j] = 0; + return (split); +} diff --git a/libft/ft_strcat.c b/libft/ft_strcat.c new file mode 100755 index 0000000..6916a5e --- /dev/null +++ b/libft/ft_strcat.c @@ -0,0 +1,32 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strcat.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/11/21 19:20:36 by fgras-ca #+# #+# */ +/* Updated: 2023/11/21 19:28:29 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +char *ft_strcat(char *dest, const char *src) +{ + char *save; + + save = dest; + while (*dest) + { + dest++; + } + while (*src) + { + *dest = *src; + dest++; + src++; + } + *dest = '\0'; + return (save); +} diff --git a/libft/ft_strchr.c b/libft/ft_strchr.c new file mode 100755 index 0000000..482fac2 --- /dev/null +++ b/libft/ft_strchr.c @@ -0,0 +1,32 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strchr.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/09 14:27:10 by fgras-ca #+# #+# */ +/* Updated: 2023/02/21 10:54:39 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +char *ft_strchr(const char *s, int c) + +{ + int i; + char *str; + + str = (char *)s; + i = 0; + while (str[i]) + { + if (str[i] == (char)c) + return (&str[i]); + i++; + } + if (str[i] == (char)c) + return (&str[i]); + return (0); +} diff --git a/libft/ft_strcmp.c b/libft/ft_strcmp.c new file mode 100755 index 0000000..d8f2c11 --- /dev/null +++ b/libft/ft_strcmp.c @@ -0,0 +1,23 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strcmp.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/11/14 16:57:42 by fgras-ca #+# #+# */ +/* Updated: 2023/11/14 17:10:27 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +int ft_strcmp(const char *s1, const char *s2) +{ + while (*s1 && (*s1 == *s2)) + { + s1++; + s2++; + } + return (*(const unsigned char *)s1 - *(const unsigned char *)s2); +} diff --git a/libft/ft_strcpy.c b/libft/ft_strcpy.c new file mode 100755 index 0000000..a738a2f --- /dev/null +++ b/libft/ft_strcpy.c @@ -0,0 +1,28 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strcpy.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/11/21 19:23:08 by fgras-ca #+# #+# */ +/* Updated: 2023/11/21 19:26:36 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +char *ft_strcpy(char *dest, const char *src) +{ + char *save; + + save = dest; + while (*src) + { + *dest = *src; + dest++; + src++; + } + *dest = '\0'; + return (save); +} diff --git a/libft/ft_strdup.c b/libft/ft_strdup.c new file mode 100755 index 0000000..7d6bfb5 --- /dev/null +++ b/libft/ft_strdup.c @@ -0,0 +1,31 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strdup.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/11 18:40:02 by fgras-ca #+# #+# */ +/* Updated: 2023/12/10 12:25:07 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +char *ft_strdup(const char *s) +{ + char *str; + size_t i; + + str = (char *)malloc(sizeof(char) * (ft_strlen(s) + 1)); + if (!str) + return (NULL); + i = 0; + while (s[i]) + { + str[i] = s[i]; + i++; + } + str[i] = 0; + return (str); +} diff --git a/libft/ft_striteri.c b/libft/ft_striteri.c new file mode 100755 index 0000000..36d249c --- /dev/null +++ b/libft/ft_striteri.c @@ -0,0 +1,25 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_striteri.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/16 14:25:00 by fgras-ca #+# #+# */ +/* Updated: 2023/11/14 17:08:02 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +void ft_striteri(char *s, void (*f)(unsigned int, char*)) +{ + unsigned int i; + + if (!s) + return ; + i = 0; + while (s[i]) + { + f(i, &s[i]); + i++; + } +} diff --git a/libft/ft_strjoin.c b/libft/ft_strjoin.c new file mode 100755 index 0000000..8be2950 --- /dev/null +++ b/libft/ft_strjoin.c @@ -0,0 +1,39 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strjoin.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/13 16:54:51 by fgras-ca #+# #+# */ +/* Updated: 2023/03/13 13:58:13 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +char *ft_strjoin(char const *s1, char const *s2) +{ + char *new_s; + size_t i; + size_t j; + + if (!s1 || !s2) + return (0); + new_s = (char *)malloc(sizeof(char) * (ft_strlen(s1) + ft_strlen(s2) + 1)); + if (!new_s) + return (0); + i = 0; + j = 0; + while (s1[i]) + { + new_s[j] = s1[i]; + i++; + j++; + } + i = 0; + while (s2[i]) + new_s[j++] = s2[i++]; + new_s[j] = '\0'; + return (new_s); +} diff --git a/libft/ft_strlcat.c b/libft/ft_strlcat.c new file mode 100755 index 0000000..4521530 --- /dev/null +++ b/libft/ft_strlcat.c @@ -0,0 +1,33 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strlcat.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/08 14:10:58 by fgras-ca #+# #+# */ +/* Updated: 2023/11/14 17:09:41 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +size_t ft_strlcat(char *dst, const char *src, size_t size) +{ + size_t i; + size_t dst_len; + + i = 0; + if (!dst && !size) + return (0); + dst_len = ft_strlen(dst); + if (size <= dst_len) + return (size + ft_strlen(src)); + while (src[i] && i < size - dst_len -1) + { + dst[dst_len + i] = src[i]; + i++; + } + dst[dst_len + i] = 0; + return (dst_len + ft_strlen(src)); +} diff --git a/libft/ft_strlcpy.c b/libft/ft_strlcpy.c new file mode 100755 index 0000000..55734e0 --- /dev/null +++ b/libft/ft_strlcpy.c @@ -0,0 +1,32 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strlcpy.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/08 13:24:31 by fgras-ca #+# #+# */ +/* Updated: 2023/02/08 13:33:32 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +size_t ft_strlcpy(char *dst, const char *src, size_t size) +{ + size_t i; + + i = 0; + if (size > 0) + { + while (src[i] && i < (size - 1)) + { + dst[i] = src[i]; + i++; + } + dst[i] = 0; + } + while (src[i]) + i++; + return (i); +} diff --git a/libft/ft_strlen.c b/libft/ft_strlen.c new file mode 100755 index 0000000..801345d --- /dev/null +++ b/libft/ft_strlen.c @@ -0,0 +1,23 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strlen.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/03 14:10:21 by fgras-ca #+# #+# */ +/* Updated: 2023/02/03 14:17:21 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +size_t ft_strlen(const char *s) +{ + size_t i; + + i = 0; + while (s[i]) + i++; + return (i); +} diff --git a/libft/ft_strmapi.c b/libft/ft_strmapi.c new file mode 100755 index 0000000..0178510 --- /dev/null +++ b/libft/ft_strmapi.c @@ -0,0 +1,33 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strmapi.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/16 13:38:52 by fgras-ca #+# #+# */ +/* Updated: 2023/11/14 17:04:43 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +char *ft_strmapi(const char *s, char (*f)(unsigned int, char)) +{ + char *result; + unsigned int i; + + if (!s) + return (0); + result = malloc(sizeof(char) * (ft_strlen(s) + 1)); + if (!result) + return (0); + i = 0; + while (s[i]) + { + result[i] = f(i, s[i]); + i++; + } + result[i] = 0; + return (result); +} diff --git a/libft/ft_strncmp.c b/libft/ft_strncmp.c new file mode 100755 index 0000000..d5d1d88 --- /dev/null +++ b/libft/ft_strncmp.c @@ -0,0 +1,29 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strncmp.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/09 17:12:38 by fgras-ca #+# #+# */ +/* Updated: 2023/02/14 13:26:15 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +int ft_strncmp(const char *s1, const char *s2, size_t n) +{ + size_t i; + + i = 0; + if (n == 0) + { + return (0); + } + while (s1[i] == s2[i] && (s1[i] != '\0' || s2[i] != '\0') && i < (n - 1)) + { + i++; + } + return ((unsigned char)s1[i] - (unsigned char)s2[i]); +} diff --git a/libft/ft_strncpy.c b/libft/ft_strncpy.c new file mode 100755 index 0000000..613eaa0 --- /dev/null +++ b/libft/ft_strncpy.c @@ -0,0 +1,31 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strncpy.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/11/27 20:03:19 by fgras-ca #+# #+# */ +/* Updated: 2023/12/07 11:56:51 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +char *ft_strncpy(char *dest, char *src, unsigned int n) +{ + unsigned int i; + + i = 0; + while (src[i] != '\0' && i < n) + { + dest[i] = src[i]; + ++i; + } + while (i < n) + { + dest[i] = '\0'; + i++; + } + return (dest); +} diff --git a/libft/ft_strnstr.c b/libft/ft_strnstr.c new file mode 100755 index 0000000..d15e922 --- /dev/null +++ b/libft/ft_strnstr.c @@ -0,0 +1,41 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strnstr.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/11 14:31:40 by fgras-ca #+# #+# */ +/* Updated: 2023/02/21 10:08:36 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +char *ft_strnstr(const char *haystack, const char *needle, size_t len) +{ + size_t i; + size_t j; + + i = 0; + if (needle == haystack) + return ((char *)haystack); + if (!len && !haystack) + return (0); + while (haystack[i] != '\0') + { + j = 0; + while (haystack[i + j] == needle[j] && (i + j) < len) + { + if (haystack[i + j] == '\0' && needle[j] == '\0') + { + return ((char *)&haystack[j]); + } + j++; + } + if (needle[j] == '\0') + return ((char *)(haystack + i)); + i++; + } + return (NULL); +} diff --git a/libft/ft_strrchr.c b/libft/ft_strrchr.c new file mode 100755 index 0000000..4c09b3a --- /dev/null +++ b/libft/ft_strrchr.c @@ -0,0 +1,29 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strrchr.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/09 16:10:11 by fgras-ca #+# #+# */ +/* Updated: 2023/02/14 15:36:23 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +char *ft_strrchr(const char *s, int c) +{ + int i; + + i = 0; + while (s[i]) + i++; + while (i >= 0) + { + if (s[i] == (char)c) + return ((char *)(s + i)); + i--; + } + return (0); +} diff --git a/libft/ft_strstr.c b/libft/ft_strstr.c new file mode 100755 index 0000000..59afb4c --- /dev/null +++ b/libft/ft_strstr.c @@ -0,0 +1,42 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strstr.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/11/14 20:54:44 by fgras-ca #+# #+# */ +/* Updated: 2023/11/14 21:08:57 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +char *ft_strstr(const char *haystack, const char *needle) +{ + const char *p; + const char *beginning; + const char *n; + + p = haystack; + if (*needle == '\0') + return ((char *)haystack); + while (*p != '\0') + { + if (*p == *needle) + { + beginning = p; + n = needle; + while (*p == *n && *n != '\0' && *p != '\0') + { + p++; + n++; + } + if (*n == '\0') + return ((char *)beginning); + p = beginning; + } + p++; + } + return (NULL); +} diff --git a/libft/ft_strtok.c b/libft/ft_strtok.c new file mode 100755 index 0000000..ba4583f --- /dev/null +++ b/libft/ft_strtok.c @@ -0,0 +1,83 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strtok.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/11/14 17:14:45 by fgras-ca #+# #+# */ +/* Updated: 2023/12/07 11:41:34 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +static char *init_str_and_lasts(char **lasts, char *str) +{ + if (str == NULL) + { + str = *lasts; + if (str == NULL) + return (NULL); + } + else + { + *lasts = str; + } + return (str); +} + +static char *find_token_start(char **lasts, const char *delim) +{ + int ch; + + ch = **lasts; + while (ch != '\0' && ft_strchr(delim, ch) != NULL) + { + (*lasts)++; + ch = **lasts; + } + if (**lasts == '\0') + { + *lasts = NULL; + return (NULL); + } + return (*lasts); +} + +static char *find_token_end(char **lasts, const char *delim) +{ + int ch; + char *str; + + str = *lasts; + ch = **lasts; + while (ch != '\0' && ft_strchr(delim, ch) == NULL) + { + (*lasts)++; + ch = **lasts; + } + if (**lasts != '\0') + { + **lasts = '\0'; + (*lasts)++; + } + else + { + *lasts = NULL; + } + return (str); +} + +char *ft_strtok(char *str, const char *delim) +{ + static char *lasts; + + str = init_str_and_lasts(&lasts, str); + if (str == NULL) + return (NULL); + str = find_token_start(&lasts, delim); + if (str == NULL) + return (NULL); + return (find_token_end(&lasts, delim)); +} diff --git a/libft/ft_strtol.c b/libft/ft_strtol.c new file mode 100755 index 0000000..374a1ca --- /dev/null +++ b/libft/ft_strtol.c @@ -0,0 +1,115 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strtol.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/12/01 14:00:32 by fgras-ca #+# #+# */ +/* Updated: 2023/12/07 11:56:12 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +static int skip_whitespaces_and_sign(const char *str, int *sign) +{ + int i; + + i = 0; + while (str[i] == ' ' || (str[i] >= '\t' && str[i] <= '\r')) + i++; + if (str[i] == '+' || str[i] == '-') + { + if (str[i] == '-') + *sign = -1; + i++; + } + return (i); +} + +static int determine_base(const char *str, int *base, int index) +{ + if ((*base == 0 || *base == 16) && str[index] == '0' + && (str[index + 1] == 'x' || str[index + 1] == 'X')) + { + *base = 16; + index += 2; + } + else if (*base == 0) + { + if (str[index] == '0') + *base = 8; + else + *base = 10; + } + return (index); +} + +static int check_base(const char *str, int *base, int *sign) +{ + int i; + + *sign = 1; + i = skip_whitespaces_and_sign(str, sign); + i = determine_base(str, base, i); + return (i); +} + +static long convert_strtol(const char *str, int base, int sign) +{ + long result; + int digit; + + result = 0; + while (*str) + { + digit = 0; + if (*str >= '0' && *str <= '9') + digit = *str - '0'; + else if (*str >= 'A' && *str <= 'Z') + digit = *str - 'A' + 10; + else if (*str >= 'a' && *str <= 'z') + digit = *str - 'a' + 10; + else + break ; + if (digit >= base) + break ; + if (sign > 0 && result > (LONG_MAX - digit) / base) + return (errno = ERANGE, LONG_MAX); + if (sign < 0 && result < (LONG_MIN + digit) / base) + return (errno = ERANGE, LONG_MIN); + result = result * base + digit; + str++; + } + return (result * sign); +} + +long ft_strtol(const char *str, char **endptr, int base) +{ + int sign; + int i; + long result; + + if (base < 0 || base == 1 || base > 36) + { + if (endptr) + *endptr = (char *)str; + return (0); + } + i = check_base(str, &base, &sign); + result = convert_strtol(str + i, base, sign); + if (endptr) + *endptr = (char *)(str + i); + while (*str) + { + if ((*str >= '0' && *str <= '9' && *str - '0' < base) + || (*str >= 'A' && *str <= 'Z' && *str - 'A' + 10 < base) + || (*str >= 'a' && *str <= 'z' && *str - 'a' + 10 < base)) + *endptr = (char *)(str + 1); + else + break ; + str++; + } + return (result); +} diff --git a/libft/ft_strtrim.c b/libft/ft_strtrim.c new file mode 100755 index 0000000..a162893 --- /dev/null +++ b/libft/ft_strtrim.c @@ -0,0 +1,52 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strtrim.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/14 16:30:26 by fgras-ca #+# #+# */ +/* Updated: 2023/03/13 14:12:41 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +static int char_in_set(char c, char const *set) +{ + size_t i; + + i = 0; + while (set[i]) + { + if (set[i] == c) + return (1); + i++; + } + return (0); +} + +char *ft_strtrim(char const *s1, char const *set) +{ + char *str; + size_t i; + size_t start; + size_t end; + + if (!s1) + return (0); + start = 0; + while (s1[start] && char_in_set(s1[start], set)) + start++; + end = ft_strlen(s1); + while (end > start && char_in_set(s1[end - 1], set)) + end--; + str = (char *)malloc(sizeof(*s1) * (end - start + 1)); + if (!str) + return (0); + i = 0; + while (start < end) + str[i++] = s1[start++]; + str[i] = 0; + return (str); +} diff --git a/libft/ft_substr.c b/libft/ft_substr.c new file mode 100755 index 0000000..11b1e8c --- /dev/null +++ b/libft/ft_substr.c @@ -0,0 +1,37 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_substr.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/13 15:40:49 by fgras-ca #+# #+# */ +/* Updated: 2023/11/14 17:07:20 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +char *ft_substr(char const *s, unsigned int start, size_t len) +{ + char *new_s; + size_t i; + size_t j; + + new_s = (char *)malloc(sizeof(char) * (len + 1)); + if (!s || !new_s) + return (NULL); + i = 0; + j = 0; + while (s[i]) + { + if (i >= start && j < len) + { + new_s[j] = s[i]; + j++; + } + i++; + } + new_s[j] = '\0'; + return (new_s); +} diff --git a/libft/ft_tolower.c b/libft/ft_tolower.c new file mode 100755 index 0000000..b7378bb --- /dev/null +++ b/libft/ft_tolower.c @@ -0,0 +1,20 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_tolower.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/09 14:09:59 by fgras-ca #+# #+# */ +/* Updated: 2023/02/14 13:36:02 by fgras-ca ### ########.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 100755 index 0000000..102da50 --- /dev/null +++ b/libft/ft_toupper.c @@ -0,0 +1,20 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_toupper.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/08 16:02:00 by fgras-ca #+# #+# */ +/* Updated: 2023/02/14 13:36:40 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +int ft_toupper(int c) +{ + if (c >= 97 && c <= 122) + c -= 32; + return (c); +} diff --git a/libft/libft.h b/libft/libft.h new file mode 100755 index 0000000..f93a452 --- /dev/null +++ b/libft/libft.h @@ -0,0 +1,85 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* libft.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/02/12 10:46:53 by fgras-ca #+# #+# */ +/* Updated: 2023/12/07 11:47:27 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef LIBFT_H +# define LIBFT_H + +# include +# include +# include +# include +# include +# include +# include +# include + +typedef struct s_list +{ + void *content; + struct s_list *next; +} t_list; + +int ft_isalpha(int c); +int ft_isdigit(int c); +int ft_isalnum(int c); +int ft_isascii(int c); +int ft_isprint(int c); +int ft_toupper(int c); +int ft_tolower(int c); +int ft_strcmp(const char *s1, const char *s2); +int ft_strncmp(const char *s1, const char *s2, size_t n); +int ft_strcmp(const char *s1, const char *s2); +int ft_memcmp(const void *s1, const void *s2, size_t n); +int ft_atoi(const char *nptr); +int ft_lstsize(t_list *lst); +void *ft_memset(void *s, int c, size_t n); +void ft_bzero(void *ptr, size_t len); +void *ft_memcpy(void *dest, const void *src, size_t n); +void *ft_memmove(void *dest, const void *src, size_t n); +void *ft_memchr(const void *s, int c, size_t n); +void *ft_calloc(size_t nmemb, size_t size); +void ft_putchar_fd(char c, int fd); +void ft_putstr_fd(char *s, int fd); +void ft_putendl_fd(char *s, int fd); +void ft_putnbr_fd(int n, int fd); +void ft_striteri(char *s, void (*f)(unsigned int, char*)); +void ft_lstadd_front(t_list **lst, t_list *new); +void ft_lstadd_back(t_list **lst, t_list *new); +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 *)); +size_t ft_strlen(const char *s); +size_t ft_strlcpy(char *dst, const char *src, size_t size); +size_t ft_strlcat(char *dst, const char *src, size_t size); +char *ft_strchr(const char *s, int c); +char *ft_strrchr(const char *s, int c); +char *ft_strtok(char *str, const char *delim); +char *ft_strnstr(const char *haystack, const char *needle, size_t len); +char *ft_strdup(const char *s); +char *ft_strstr(const char *haystack, const char *needle); +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(const char *s, char (*f)(unsigned int, char)); +char *ft_strncpy(char *dest, char *src, unsigned int n); +char **ft_split(char const *s, char c); +void *ft_reallocarray(void *optr, size_t nmemb, size_t size, size_t oldsize); +void *ft_realloc(void *ptr, size_t newsize, size_t oldsize); +char *ft_itoa(int n); +char *ft_strcat(char *dest, const char *src); +char *ft_strcpy(char *dest, const char *src); +t_list *ft_lstnew(void *content); +t_list *ft_lstlast(t_list *lst); +t_list *ft_lstmap(t_list *lst, void *(*f)(void *), void (*del)(void *)); +long ft_strtol(const char *str, char **endptr, int base); + +#endif diff --git a/minishell.h b/minishell.h new file mode 100755 index 0000000..20dbdb1 --- /dev/null +++ b/minishell.h @@ -0,0 +1,271 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* minishell.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/11/07 16:11:33 by fgras-ca #+# #+# */ +/* Updated: 2023/12/10 14:08:16 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef MINISHELL_H +# define MINISHELL_H + +# include "libft/libft.h" +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include + +# define RST "\033[0m" +# define GRAY "\033[0;90m" +# define RED "\033[0;91m" +# define GREEN "\033[0;92m" +# define YELLOW "\033[0;93m" +# define BLUE "\033[0;94m" +# define MAGENTA "\033[0;95m" +# define CYAN "\033[0;96m" +# define WHITE "\033[0;97m" +# define ORANGE "\033[38;5;214m" + +# define MAX_ARGS 10000 +# define DELIM " \t\r\n\a" +# define CONTINUE_SHELL 0 +# define EXIT_SHELL 1 + +typedef enum s_redirection_mode +{ + REDIRECT_IN, + REDIRECT_OUT, + REDIRECT_APPEND, + REDIRECT_HEREDOC, + REDIRECT_UNKNOWN +} t_redirection_mode; + +typedef enum s_state +{ + NORMAL, + SINGLE_QUOTE, + DOUBLE_QUOTE +} t_State; + +typedef struct s_tokenizer +{ + t_State state; + char **tokens; + char *token; + int token_length; + int input_pos; + int token_pos; + bool in_quotes; + bool within_single_quotes; + bool within_double_quotes; + bool variable; + bool symbol; +} t_Tokenizer; + +typedef struct s_minishell +{ + char **builtin_str; + char **environ; + int (**builtin_func)(char **, struct s_minishell *); + int last_exit_status; + t_Tokenizer *tokenizer; + bool is_piped; + int exit_status; +} t_minishell; + +typedef struct s_command +{ + char *command; + char **args; + int arg_count; +} t_command; + +typedef struct s_redirection +{ + int stdin_backup; + int stdout_backup; +} t_redirection; + +typedef struct s_pipe_struct +{ + int fds[2]; +} t_pipe_struct; + +typedef struct s_command_node +{ + t_command *command; + struct s_command_node *left; + struct s_command_node *right; +} t_command_node; + +typedef struct s_process_token_params +{ + char **tokens; + int *token_index; + t_command **current_command; + t_command_node **root; + t_minishell *shell; + int command_count; +} t_process_token_params; + +typedef struct s_child_process_params +{ + int i; + int *pipe_fds; + int command_count; + int fd; + t_command **commands; + t_minishell *shell; +} t_child_process_params; + +typedef struct s_process_params +{ + int *pipe_fds; + t_command **commands; + t_minishell *shell; + int command_count; + int fd; +} t_process_params; + +typedef int (*t_builtin_func_t)(char **, t_minishell *); + +//prompt +void prompt_loop(t_minishell *shell, int fd); +t_minishell init_minishell(char **envp, char **builtin_str, + int (**builtin_func)(char **, t_minishell *)); +//history +void display_history_entry(HIST_ENTRY **the_history_list, int i); +void display_history_list(void); +void search_in_history(HIST_ENTRY **the_history_list, + const char *search_string); +void search_history(void); +//builtins +int builtin_echo_wrapper(char **args, t_minishell *shell); +int builtin_cd(char **args, t_minishell *shell); +int builtin_echo(char **args, t_minishell *shell, int fd); +int builtin_exit(char **args, t_minishell *shell); +int builtin_env(char **args, t_minishell *shell); +int builtin_pwd(char **args, t_minishell *shell); +int builtin_export(char **args, t_minishell *shell); +int num_builtins(t_minishell *shell); +int execute_builtin(char **args, t_minishell *shell); +int builtin_unset(char **args, t_minishell *shell); +int export_set_env(char **args, t_minishell *shell); +int count_env_vars(char **environ); +char **copy_env(char **environ, int env_size); +void sort_env(char **env, int env_size); +int add_new_env_entry(t_minishell *shell, char *new_env_entry); +int replace_env_entry(t_minishell *shell, char *new_env_entry); +char *extract_name(char *env_entry); +char *extract_value(char *env_entry); +t_builtin_func_t *initialize_builtin_func(void); +//Exécutions +pid_t create_process(char *path, char **args, char **environ); +pid_t execute_external_command(char **args, char **environ); +char *find_executable(const char *cmd, char **environ); +//tokenize +char **tokenize_and_parse_input(char *input, + t_minishell *shell, int fd); +void tokenize_loop(char *input, t_Tokenizer *tk); +void init_vars(t_Tokenizer *tk, char *input); +void process_char(char input_char, t_Tokenizer *tk); +void add_token_to_list(t_Tokenizer *tk); +void free_tokens(char **tokens); +void add_special_symbol(char *input, t_Tokenizer *tk); +void handle_spaces_and_tabs(char *input, t_Tokenizer *tk); +void handle_empty_quotes(char *input, t_Tokenizer *tk); +bool is_special_symbol(char c, char next_c); +bool is_simple_symbol(char c); +void process_input_char(char *input, t_Tokenizer *tk); +void handle_other_chars(char *input, t_Tokenizer *tk); +void handle_special_symbol(char *input, t_Tokenizer *tk); +void handle_spaces_or_tabs(char *input, t_Tokenizer *tk); +bool is_space_or_tab(char current_char); +void handle_quote_transition(char *input, t_Tokenizer *tk); +bool is_quote_transition(char current_char, t_Tokenizer *tk); +char *replace_env_vars_in_string(const char *str, + t_minishell *shell); +//quotes +void handle_normal_state(char input_char, t_Tokenizer *tk); +void handle_single_quote_state(char input_char, t_Tokenizer *tk); +void handle_double_quote_state(char input_char, t_Tokenizer *tk); +char **handle_unclosed_quotes(char ***tokens, int token_pos); +int are_only_quotes(char **tokens); +//var $ +char *get_variable_value(const char *variable_name, + t_minishell *shell); +const char *skip_dollar(const char *variable_name); +void reverse_str(char *str, int length); +char *search_env_variable(const char *name_to_search, + t_minishell *shell); +//utils +char *get_env_value(const char *key, char **environ); +int is_only_spaces(const char *str); +//gestions signaux ctrl-c ctrl-D ctrl- +void handle_sigint(int sig); +void handle_sigquit(int sig); +void setup_signal_handlers(void); +//parsing +void parse_tokens(char **tokens, t_minishell *shell, int fd); +bool is_pipe_token(char *token, t_minishell *shell); +bool is_redirection_token(char *token); +bool is_variable_token(char *token); +void add_token_to_command_wrapper(t_command **command, + char *token); +int is_variable_resolvable(char *token, t_State current_state); +void handle_variable_and_other_tokens( + t_process_token_params *params); +void handle_pipe_and_redirection(t_process_token_params *params, + int fd); +void execute_and_free_tree(t_command_node *root, + t_minishell *shell, int command_count, int fd); +int check_syntax_error(char **tokens, int token_index, + bool in_quotes, t_minishell *shell); +//redirections +void process_redirection(t_process_token_params *params, + t_command *commands, t_minishell *shell, int fd); +void save_standard_descriptors(t_redirection *redir); +void restore_standard_descriptors(t_redirection *redir); +void heredoc_input(const char *delimiter); +void configure_redirection(char *file, int mode); +//pipes +void process_pipe(t_command **command, t_minishell *shell, + int command_count, int fd); +void heredoc_input(const char *delimiter); +void close_all_pipes(int *pipe_fds, int count); +void setup_child_process(t_child_process_params *params); +//command +void reset_command(t_command *command); +void free_command(t_command *command); +void add_token_to_command(t_command *command, char *token); +void execute_command(t_command *command, + t_minishell *shell, int fd); +bool is_builtin_command(const char *command, t_minishell *shell); +t_command *create_new_command(void); +char **build_args_array(t_command *command); +void free_args_array(char **args); +int execute_builtin_and_free(char **args, + t_minishell *shell, int fd); +//tree +t_command_node *create_command_node(t_command *command); +void add_node_to_tree(t_command_node **root, + t_command_node *new_node); +void execute_command_tree(t_command_node *node, + t_minishell *shell, int command_count, int fd); +void free_command_tree(t_command_node *node); + +#endif diff --git a/parsing/herodoc.c b/parsing/herodoc.c new file mode 100755 index 0000000..d513972 --- /dev/null +++ b/parsing/herodoc.c @@ -0,0 +1,78 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* herodoc.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/12/01 15:49:41 by fgras-ca #+# #+# */ +/* Updated: 2023/12/07 14:16:55 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +static void read_and_write_input(int write_end, const char *delimiter) +{ + char buffer[1024]; + ssize_t num_read; + char *newline; + + while (1) + { + printf("> "); + fflush(stdout); + num_read = read(STDIN_FILENO, buffer, sizeof(buffer) - 1); + if (num_read <= 0) + break ; + buffer[num_read] = '\0'; + if (ft_strncmp(buffer, delimiter, ft_strlen(delimiter)) == 0) + { + newline = ft_strchr(buffer, '\n'); + if (newline != NULL && newline - buffer + == (ptrdiff_t)ft_strlen(delimiter)) + break ; + } + write(write_end, buffer, num_read); + } +} + +static void child_process(int *pipe_fds, const char *delimiter) +{ + close(pipe_fds[0]); + read_and_write_input(pipe_fds[1], delimiter); + close(pipe_fds[1]); + exit(EXIT_SUCCESS); +} + +static void parent_process(int *pipe_fds) +{ + close(pipe_fds[1]); + dup2(pipe_fds[0], STDIN_FILENO); + close(pipe_fds[0]); +} + +void heredoc_input(const char *delimiter) +{ + int pipe_fds[2]; + pid_t pid; + + if (pipe(pipe_fds) == -1) + { + perror("pipe"); + exit(EXIT_FAILURE); + } + pid = fork(); + if (pid == -1) + { + perror("fork"); + exit(EXIT_FAILURE); + } + if (pid == 0) + child_process(pipe_fds, delimiter); + else + { + parent_process(pipe_fds); + waitpid(pid, NULL, 0); + } +} diff --git a/parsing/parse.c b/parsing/parse.c new file mode 100755 index 0000000..5d08d78 --- /dev/null +++ b/parsing/parse.c @@ -0,0 +1,113 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* parse.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/11/29 21:03:27 by fgras-ca #+# #+# */ +/* Updated: 2023/12/10 14:00:23 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +static void finalize_command(t_command **current_command, t_command_node **root) +{ + t_command_node *new_node; + + if (*current_command && (*current_command)->command) + { + new_node = create_command_node(*current_command); + add_node_to_tree(root, new_node); + } + else if (*current_command) + { + free_command(*current_command); + } +} + +static bool handle_syntax_error_and_free(t_process_token_params *params, + t_minishell *shell) +{ + char *current_token; + bool sb; + + current_token = params->tokens[*params->token_index]; + sb = shell->tokenizer->symbol; + if (sb && (is_pipe_token(current_token, shell) + || is_redirection_token(current_token))) + { + if (check_syntax_error(params->tokens, + *params->token_index, shell->tokenizer->in_quotes, shell)) + { + if (*(params->current_command) != NULL) + { + free_command(*(params->current_command)); + *(params->current_command) = NULL; + } + return (true); + } + } + return (false); +} + +static void process_single_token(t_process_token_params *params, + t_minishell *shell, int fd) +{ + char *current_token; + + current_token = params->tokens[*params->token_index]; + if (shell->tokenizer->symbol && (is_pipe_token(current_token, shell) + || is_redirection_token(current_token))) + { + handle_pipe_and_redirection(params, fd); + } + else + { + handle_variable_and_other_tokens(params); + } +} + +static void process_tokens(t_process_token_params *params, + t_minishell *shell, int fd) +{ + while (params->tokens[*params->token_index] != NULL) + { + if (handle_syntax_error_and_free(params, shell)) + { + return ; + } + process_single_token(params, shell, fd); + (*params->token_index)++; + } +} + +void parse_tokens(char **tokens, t_minishell *shell, int fd) +{ + t_command_node *root; + t_command *current_command; + int token_index; + int error_detected; + t_process_token_params params; + + token_index = 0; + current_command = NULL; + root = NULL; + error_detected = 0; + params.tokens = tokens; + params.token_index = &token_index; + params.current_command = ¤t_command; + params.root = &root; + params.shell = shell; + params.command_count = 1; + process_tokens(¶ms, shell, fd); + if (current_command && current_command->command) + { + finalize_command(¤t_command, &root); + if (!error_detected) + execute_and_free_tree(root, shell, params.command_count, fd); + } + else if (current_command) + free_command(current_command); +} diff --git a/parsing/parse_error.c b/parsing/parse_error.c new file mode 100755 index 0000000..e536890 --- /dev/null +++ b/parsing/parse_error.c @@ -0,0 +1,45 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* parse_error.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/12/07 13:00:24 by fgras-ca #+# #+# */ +/* Updated: 2023/12/09 19:25:39 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +void execute_and_free_tree(t_command_node *root, + t_minishell *shell, int command_count, int fd) +{ + if (root) + { + execute_command_tree(root, shell, command_count, fd); + free_command_tree(root); + } +} + +int check_syntax_error(char **tokens, int token_index, + bool in_quotes, t_minishell *shell) +{ + if (in_quotes) + { + return (0); + } + if (is_redirection_token(tokens[token_index]) + || is_pipe_token(tokens[token_index], shell)) + { + if (token_index == 0 || tokens[token_index + 1] == NULL) + { + write(2, RED"bash: erreur de syntaxe près du symbole inattendu " + RST, 58); + write(2, tokens[token_index], ft_strlen(tokens[token_index])); + write(2, "\n", 1); + return (1); + } + } + return (0); +} diff --git a/parsing/parse_redirections.c b/parsing/parse_redirections.c new file mode 100755 index 0000000..e42241c --- /dev/null +++ b/parsing/parse_redirections.c @@ -0,0 +1,87 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* parse_redirections.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/12/01 15:25:07 by fgras-ca #+# #+# */ +/* Updated: 2023/12/10 13:55:02 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +void handle_pipe_and_redirection(t_process_token_params *params, int fd) +{ + t_command_node *new_node; + + if (is_pipe_token(params->tokens[*params->token_index], params->shell)) + { + if (*params->current_command && (*params->current_command)->command) + { + new_node = create_command_node(*params->current_command); + add_node_to_tree(params->root, new_node); + *params->current_command = create_new_command(); + params->command_count++; + } + } + else if (is_redirection_token(params->tokens[*params->token_index])) + { + if (*params->current_command && (*params->current_command)->command) + { + process_redirection + (params, *params->current_command, params->shell, fd); + } + } +} + +void resolve_variable_and_add_to_command(t_process_token_params *params, + char *token) +{ + char *resolved_value; + + resolved_value = get_variable_value(token, params->shell); + add_token_to_command_wrapper(params->current_command, resolved_value); + free(resolved_value); +} + +static void handle_variable_token(t_process_token_params *params) +{ + char *token; + t_State current_state; + + token = params->tokens[*params->token_index]; + current_state = params->shell->tokenizer->state; + if (is_variable_resolvable(token, current_state)) + { + resolve_variable_and_add_to_command(params, token); + } + else + { + add_token_to_command_wrapper(params->current_command, token); + } +} + +static void handle_non_variable_token(t_process_token_params *params) +{ + add_token_to_command_wrapper(params->current_command, + params->tokens[*params->token_index]); +} + +void handle_variable_and_other_tokens(t_process_token_params *params) +{ + char *current_token; + bool variable; + + current_token = params->tokens[*params->token_index]; + variable = params->shell->tokenizer->variable; + if (!variable && is_variable_token(current_token)) + { + handle_variable_token(params); + } + else + { + handle_non_variable_token(params); + } +} diff --git a/parsing/parse_utils.c b/parsing/parse_utils.c new file mode 100755 index 0000000..dd7eacc --- /dev/null +++ b/parsing/parse_utils.c @@ -0,0 +1,54 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* parse_utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/12/07 09:58:11 by fgras-ca #+# #+# */ +/* Updated: 2023/12/09 19:09:08 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +bool is_pipe_token(char *token, t_minishell *shell) +{ + (void)shell; + return (strcmp(token, "|") == 0); +} + +bool is_redirection_token(char *token) +{ + static const char *redirections[] = {">", "<", ">>", "<<", NULL}; + int i; + + i = 0; + while (redirections[i] != NULL) + { + if (ft_strcmp(token, redirections[i]) == 0) + return (true); + i++; + } + return (false); +} + +bool is_variable_token(char *token) +{ + return (token[0] == '$' && token[1] != '\0'); +} + +void add_token_to_command_wrapper(t_command **command, char *token) +{ + if (!*command) + { + *command = create_new_command(); + } + add_token_to_command(*command, token); +} + +int is_variable_resolvable(char *token, t_State current_state) +{ + return ((current_state == DOUBLE_QUOTE || (token[0] == '$')) + && (current_state != SINGLE_QUOTE)); +} diff --git a/parsing/pipe.c b/parsing/pipe.c new file mode 100755 index 0000000..be4f25b --- /dev/null +++ b/parsing/pipe.c @@ -0,0 +1,92 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* pipe.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/11/28 19:21:38 by fgras-ca #+# #+# */ +/* Updated: 2023/12/09 19:21:39 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +static void create_and_handle_processes(t_process_params *params) +{ + int i; + pid_t pid; + t_child_process_params child_params; + + i = 0; + while (i < params->command_count) + { + pid = fork(); + if (pid == 0) + { + child_params = (t_child_process_params){i, params->pipe_fds, + params->command_count, params->fd, + params->commands, params->shell}; + setup_child_process(&child_params); + } + else if (pid < 0) + { + perror("fork"); + exit(EXIT_FAILURE); + } + i++; + } +} + +static void initialize_pipes(int *pipe_fds, int command_count) +{ + int i; + + i = 0; + while (i < command_count - 1) + { + if (pipe(pipe_fds + i * 2) < 0) + { + perror("pipe"); + exit(EXIT_FAILURE); + } + i++; + } +} + +static void wait_for_all_processes(int command_count) +{ + int i; + + i = 0; + while (i < command_count) + { + wait(NULL); + i++; + } +} + +void process_pipe(t_command **commands, + t_minishell *shell, int command_count, int fd) +{ + int *pipe_fds; + t_process_params params; + + if (command_count == 1) + { + execute_command(commands[0], shell, fd); + return ; + } + pipe_fds = malloc(2 * (command_count - 1) * sizeof(int)); + if (!pipe_fds) + { + perror("malloc"); + exit(EXIT_FAILURE); + } + initialize_pipes(pipe_fds, command_count); + params = (t_process_params){pipe_fds, commands, shell, command_count, fd}; + create_and_handle_processes(¶ms); + close_all_pipes(pipe_fds, 2 * (command_count - 1)); + wait_for_all_processes(command_count); + free(pipe_fds); +} diff --git a/parsing/pipe_utils.c b/parsing/pipe_utils.c new file mode 100755 index 0000000..b038f31 --- /dev/null +++ b/parsing/pipe_utils.c @@ -0,0 +1,40 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* pipe_utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/12/09 17:16:52 by fgras-ca #+# #+# */ +/* Updated: 2023/12/09 18:45:08 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +void close_all_pipes(int *pipe_fds, int count) +{ + int i; + + i = 0; + while (i < count) + { + close(pipe_fds[i]); + i++; + } +} + +void setup_child_process(t_child_process_params *params) +{ + if (params->i != 0) + { + dup2(params->pipe_fds[(params->i - 1) * 2], STDIN_FILENO); + } + if (params->i != params->command_count - 1) + { + dup2(params->pipe_fds[params->i * 2 + 1], STDOUT_FILENO); + } + close_all_pipes(params->pipe_fds, 2 * (params->command_count - 1)); + execute_command(params->commands[params->i], params->shell, params->fd); + exit(EXIT_SUCCESS); +} diff --git a/parsing/redirection.c b/parsing/redirection.c new file mode 100755 index 0000000..83394ba --- /dev/null +++ b/parsing/redirection.c @@ -0,0 +1,82 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* redirection.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/11/28 18:42:58 by fgras-ca #+# #+# */ +/* Updated: 2023/12/10 13:56:12 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +void configure_redirection(char *file, int mode) +{ + int fd; + + if (mode == REDIRECT_IN) + { + fd = open(file, O_RDONLY); + dup2(fd, STDIN_FILENO); + close(fd); + } + else if (mode == REDIRECT_OUT) + { + fd = open(file, O_WRONLY | O_CREAT | O_TRUNC, 0644); + dup2(fd, STDOUT_FILENO); + close(fd); + } + else if (mode == REDIRECT_APPEND) + { + fd = open(file, O_WRONLY | O_CREAT | O_APPEND, 0644); + dup2(fd, STDOUT_FILENO); + close(fd); + } + else if (mode == REDIRECT_HEREDOC) + { + heredoc_input(file); + } +} + +static t_redirection_mode get_redirection_mode(char *token) +{ + if (ft_strcmp(token, ">") == 0) + return (REDIRECT_OUT); + if (ft_strcmp(token, "<") == 0) + return (REDIRECT_IN); + if (ft_strcmp(token, ">>") == 0) + return (REDIRECT_APPEND); + if (ft_strcmp(token, "<<") == 0) + return (REDIRECT_HEREDOC); + perror(RED"Redirection non reconnue"RST); + return (REDIRECT_UNKNOWN); +} + +static void handle_redirection(char *token, t_redirection_mode redirection_mode) +{ + if (redirection_mode == REDIRECT_HEREDOC) + heredoc_input(token); + else + configure_redirection(token, redirection_mode); +} + +void process_redirection(t_process_token_params *params, t_command *commands, + t_minishell*shell, int fd) +{ + t_redirection redir; + t_redirection_mode redirection_mode; + + save_standard_descriptors(&redir); + redirection_mode + = get_redirection_mode(params->tokens[*(params->token_index)]); + if (redirection_mode == REDIRECT_UNKNOWN) + return ; + (*(params->token_index))++; + handle_redirection + (params->tokens[*(params->token_index)], redirection_mode); + execute_command(commands, shell, fd); + restore_standard_descriptors(&redir); + reset_command(*params->current_command); +} diff --git a/parsing/redirection_utils.c b/parsing/redirection_utils.c new file mode 100755 index 0000000..60571af --- /dev/null +++ b/parsing/redirection_utils.c @@ -0,0 +1,33 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* redirection_utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/12/07 12:33:34 by fgras-ca #+# #+# */ +/* Updated: 2023/12/10 13:29:36 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +void save_standard_descriptors(t_redirection *redir) +{ + redir->stdin_backup = dup(STDIN_FILENO); + redir->stdout_backup = dup(STDOUT_FILENO); +} + +void restore_standard_descriptors(t_redirection *redir) +{ + if (redir->stdin_backup != -1) + { + dup2(redir->stdin_backup, STDIN_FILENO); + close(redir->stdin_backup); + } + if (redir->stdout_backup != -1) + { + dup2(redir->stdout_backup, STDOUT_FILENO); + close(redir->stdout_backup); + } +} diff --git a/parsing/tree.c b/parsing/tree.c new file mode 100755 index 0000000..50393c9 --- /dev/null +++ b/parsing/tree.c @@ -0,0 +1,82 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* tree.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/11/30 12:03:54 by fgras-ca #+# #+# */ +/* Updated: 2023/12/10 13:56:39 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +t_command_node *create_command_node(t_command *command) +{ + t_command_node *node; + + node = malloc(sizeof(t_command_node)); + if (node == NULL) + { + return (NULL); + } + node->command = command; + node->left = NULL; + node->right = NULL; + return (node); +} + +void add_node_to_tree(t_command_node **root, t_command_node *new_node) +{ + t_command_node *current; + + if (*root == NULL) + { + *root = new_node; + } + else + { + current = *root; + while (current->right != NULL) + { + current = current->right; + } + current->right = new_node; + } +} + +void execute_command_tree(t_command_node *node, t_minishell *shell, + int command_count, int fd) +{ + t_command **commands_array; + t_command_node *current_node; + int i; + + i = 0; + current_node = node; + commands_array = malloc(sizeof(t_command *) * command_count); + while (current_node != NULL && i < command_count) + { + commands_array[i] = current_node->command; + current_node = current_node->right; + i++; + } + process_pipe(commands_array, shell, command_count, fd); + free(commands_array); +} + +void free_command_tree(t_command_node *node) +{ + if (node == NULL) + { + return ; + } + free_command_tree(node->left); + free_command_tree(node->right); + if (node->command) + { + free(node->command); + } + free(node); +} diff --git a/parsing/variable.c b/parsing/variable.c new file mode 100755 index 0000000..9d78913 --- /dev/null +++ b/parsing/variable.c @@ -0,0 +1,105 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* variable.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/11/29 21:41:34 by fgras-ca #+# #+# */ +/* Updated: 2023/12/07 14:10:45 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +static char *allocate_exit_status_str(void) +{ + char *exit_status_str; + + exit_status_str = malloc(sizeof(char) * 12); + if (exit_status_str == NULL) + { + perror("Erreur d'allocation mémoire $"); + return (NULL); + } + return (exit_status_str); +} + +static int num_to_str(int num, char *str, int base) +{ + int i; + int rem; + + i = 0; + if (num == 0) + { + str[i++] = '0'; + } + else + { + while (num != 0) + { + rem = num % base; + if (rem > 9) + str[i++] = (rem - 10) + 'a'; + else + str[i++] = rem + '0'; + num /= base; + } + } + str[i] = '\0'; + return (i); +} + +static void int_to_str(int num, char *str, int base) +{ + int isnegative; + int length; + + isnegative = 0; + if (num == 0) + { + str[0] = '0'; + str[1] = '\0'; + return ; + } + if (num < 0 && base == 10) + { + isnegative = 1; + num = -num; + } + length = num_to_str(num, str, base); + if (isnegative) + { + str[length] = '-'; + str[length + 1] = '\0'; + length++; + } + reverse_str(str, length); +} + +static char *get_exit_status_str(t_minishell *shell) +{ + char *exit_status_str; + + exit_status_str = allocate_exit_status_str(); + if (exit_status_str == NULL) + return (NULL); + int_to_str(shell->last_exit_status, exit_status_str, 10); + return (exit_status_str); +} + +char *get_variable_value(const char *variable_name, t_minishell *shell) +{ + const char *name_to_search; + char *value; + + name_to_search = skip_dollar(variable_name); + if (ft_strcmp(name_to_search, "?") == 0) + { + value = get_exit_status_str(shell); + return (value); + } + value = search_env_variable(name_to_search, shell); + return (value); +} diff --git a/parsing/variable_utils.c b/parsing/variable_utils.c new file mode 100755 index 0000000..ea72fd3 --- /dev/null +++ b/parsing/variable_utils.c @@ -0,0 +1,57 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* variable_utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/12/07 10:46:07 by fgras-ca #+# #+# */ +/* Updated: 2023/12/07 14:11:44 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +const char *skip_dollar(const char *variable_name) +{ + if (variable_name[0] == '$') + return (variable_name + 1); + return (variable_name); +} + +void reverse_str(char *str, int length) +{ + int start; + int end; + char temp; + + start = 0; + end = length - 1; + while (start < end) + { + temp = str[start]; + str[start] = str[end]; + str[end] = temp; + start++; + end--; + } +} + +char *search_env_variable(const char *name_to_search, t_minishell *shell) +{ + int i; + char *env_entry; + size_t name_len; + + name_len = ft_strlen(name_to_search); + i = 0; + while (shell->environ[i]) + { + env_entry = shell->environ[i]; + if (ft_strncmp(env_entry, name_to_search, name_len) == 0 + && env_entry[name_len] == '=') + return (ft_strdup(env_entry + name_len + 1)); + i++; + } + return (ft_strdup("")); +} diff --git a/prompt/history.c b/prompt/history.c new file mode 100755 index 0000000..66f9946 --- /dev/null +++ b/prompt/history.c @@ -0,0 +1,71 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* history.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/12/01 17:14:12 by fgras-ca #+# #+# */ +/* Updated: 2023/12/07 15:55:33 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +void display_history_entry(HIST_ENTRY **the_history_list, int i) +{ + printf("%d: %s\n", i + history_base, the_history_list[i]->line); +} + +void display_history_list(void) +{ + int i; + HIST_ENTRY **the_history_list; + + i = 0; + the_history_list = history_list(); + if (the_history_list) + { + while (the_history_list[i]) + { + display_history_entry(the_history_list, i); + i++; + } + } +} + +void search_in_history(HIST_ENTRY **the_history_list + , const char *search_string) +{ + int i; + + i = 0; + while (the_history_list[i]) + { + if (ft_strstr(the_history_list[i]->line, search_string)) + { + printf("%d: %s\n", i + history_base, the_history_list[i]->line); + } + i++; + } +} + +void search_history(void) +{ + char *search_string; + HIST_ENTRY **the_history_list; + + search_string = readline("Rechercher dans l'historique: "); + if (search_string && *search_string) + { + the_history_list = history_list(); + if (the_history_list) + { + search_in_history(the_history_list, search_string); + } + } + if (search_string) + { + free(search_string); + } +} diff --git a/prompt/init_shell.c b/prompt/init_shell.c new file mode 100755 index 0000000..02531e5 --- /dev/null +++ b/prompt/init_shell.c @@ -0,0 +1,111 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* init_shell.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/11/21 20:21:25 by fgras-ca #+# #+# */ +/* Updated: 2023/12/09 15:47:18 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +static char *create_new_env_entry(char *name, char *value) +{ + char *new_env_entry; + int name_len; + int value_len; + + name_len = ft_strlen(name); + if (value) + { + value_len = ft_strlen(value); + } + else + { + value_len = 0; + } + new_env_entry = malloc(name_len + value_len + 2); + if (!new_env_entry) + exit(EXIT_FAILURE); + ft_strcpy(new_env_entry, name); + ft_strcat(new_env_entry, "="); + if (value) + ft_strcat(new_env_entry, value); + return (new_env_entry); +} + +static char *process_env_entry(char *env_entry) +{ + char *name; + char *value; + char *new_env_entry; + + name = extract_name(env_entry); + value = extract_value(env_entry); + new_env_entry = create_new_env_entry(name, value); + free(name); + free(value); + return (new_env_entry); +} + +static void init_environ(t_minishell *shell, char **envp) +{ + int count; + int i; + + count = 0; + while (envp[count]) + count++; + shell->environ = malloc((count + 1) * sizeof(char *)); + if (!shell->environ) + exit(EXIT_FAILURE); + i = 0; + while (envp[i]) + { + shell->environ[i] = process_env_entry(envp[i]); + i++; + } + shell->environ[count] = NULL; +} + +t_minishell init_minishell(char **envp, char **builtin_str, + int (**builtin_func)(char **, t_minishell *)) +{ + t_minishell shell; + + shell.builtin_str = builtin_str; + shell.builtin_func = builtin_func; + init_environ(&shell, envp); + shell.last_exit_status = 0; + shell.tokenizer = malloc(sizeof(t_Tokenizer)); + if (!shell.tokenizer) + return (shell); + shell.tokenizer->state = NORMAL; + shell.tokenizer->tokens = NULL; + shell.tokenizer->token = NULL; + shell.tokenizer->token_length = 0; + shell.tokenizer->input_pos = 0; + shell.tokenizer->token_pos = 0; + shell.tokenizer->in_quotes = false; + shell.tokenizer->variable = 0; + shell.tokenizer->symbol = true; + shell.is_piped = false; + return (shell); +} + +bool is_builtin_command(const char *command, t_minishell *shell) +{ + int i; + + i = 0; + while (shell->builtin_str[i] != NULL) + { + if (ft_strcmp(command, shell->builtin_str[i]) == 0) + return (true); + i++; + } + return (false); +} diff --git a/prompt/main.c b/prompt/main.c new file mode 100755 index 0000000..07ffb22 --- /dev/null +++ b/prompt/main.c @@ -0,0 +1,73 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* main.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/11/14 19:37:18 by fgras-ca #+# #+# */ +/* Updated: 2023/12/09 18:52:00 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +char **initialize_builtin_str(void) +{ + char **local_builtin_str; + + local_builtin_str = malloc(8 * sizeof(char *)); + if (!local_builtin_str) + return (NULL); + local_builtin_str[0] = "cd"; + local_builtin_str[1] = "echo"; + local_builtin_str[2] = "exit"; + local_builtin_str[3] = "export"; + local_builtin_str[4] = "env"; + local_builtin_str[5] = "pwd"; + local_builtin_str[6] = "unset"; + local_builtin_str[7] = NULL; + return (local_builtin_str); +} + +t_builtin_func_t *initialize_builtin_func(void) +{ + t_builtin_func_t *local_builtin_func; + + local_builtin_func = malloc(8 * sizeof(int (*)(char **, t_minishell *))); + if (!local_builtin_func) + return (NULL); + local_builtin_func[0] = &builtin_cd; + local_builtin_func[1] = &builtin_echo_wrapper; + local_builtin_func[2] = &builtin_exit; + local_builtin_func[3] = &builtin_export; + local_builtin_func[4] = &builtin_env; + local_builtin_func[5] = &builtin_pwd; + local_builtin_func[6] = &builtin_unset; + local_builtin_func[7] = NULL; + return (local_builtin_func); +} + +int main(int argc, char **argv, char **envp) +{ + t_minishell shell; + char **local_builtin_str; + int (**local_builtin_func)(char **, t_minishell *); + int fd; + + (void)argc; + (void)argv; + fd = STDOUT_FILENO; + local_builtin_str = initialize_builtin_str(); + local_builtin_func = initialize_builtin_func(); + if (!local_builtin_str || !local_builtin_func) + { + return (1); + } + rl_bind_key('\t', rl_complete); + shell = init_minishell(envp, local_builtin_str, local_builtin_func); + prompt_loop(&shell, fd); + free(local_builtin_str); + free(local_builtin_func); + return (0); +} diff --git a/prompt/prompt.c b/prompt/prompt.c new file mode 100755 index 0000000..d794b3f --- /dev/null +++ b/prompt/prompt.c @@ -0,0 +1,57 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* prompt.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/11/07 15:51:21 by fgras-ca #+# #+# */ +/* Updated: 2023/12/09 18:49:47 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +void disable_tab_completion(void) +{ + rl_bind_key('\t', rl_insert); +} + +static void process_input_line(t_minishell *shell, char *line, int fd) +{ + if (ft_strcmp(line, "history") == 0) + { + display_history_list(); + } + else + { + tokenize_and_parse_input(line, shell, fd); + } +} + +void prompt_loop(t_minishell *shell, int fd) +{ + char *line; + int status; + + setup_signal_handlers(); + status = 1; + using_history(); + disable_tab_completion(); + while (status) + { + line = readline("\001"ORANGE"\002Minishell$> \001"RST"\002"); + if (!line) + { + write(STDOUT_FILENO, "\n", 1); + break ; + } + if (!is_only_spaces(line) && ft_strcmp(line, "") != 0) + { + add_history(line); + process_input_line(shell, line, fd); + } + free(line); + } + clear_history(); +} diff --git a/signal/ctrl.c b/signal/ctrl.c new file mode 100755 index 0000000..b44090b --- /dev/null +++ b/signal/ctrl.c @@ -0,0 +1,43 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ctrl.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/11/15 17:55:28 by fgras-ca #+# #+# */ +/* Updated: 2023/12/07 16:43:19 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +void handle_sigint(int sig) +{ + (void)sig; + write(STDOUT_FILENO, "\n", 1); + rl_on_new_line(); + rl_replace_line("", 0); + rl_redisplay(); +} + +void handle_sigquit(int sig) +{ + (void)sig; + printf("\b\b \b\b"); +} + +void setup_signal_handlers(void) +{ + struct sigaction sa_int; + struct sigaction sa_quit; + + sa_int.sa_handler = handle_sigint; + sigemptyset(&sa_int.sa_mask); + sa_int.sa_flags = SA_RESTART; + sigaction(SIGINT, &sa_int, NULL); + sa_quit.sa_handler = handle_sigquit; + sigemptyset(&sa_quit.sa_mask); + sa_quit.sa_flags = SA_RESTART; + sigaction(SIGQUIT, &sa_quit, NULL); +} diff --git a/tokenize/quotes.c b/tokenize/quotes.c new file mode 100755 index 0000000..8942694 --- /dev/null +++ b/tokenize/quotes.c @@ -0,0 +1,121 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* quotes.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/11/26 10:40:11 by fgras-ca #+# #+# */ +/* Updated: 2023/12/07 16:19:24 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +int are_only_quotes(char **tokens) +{ + int i; + + i = 0; + while (tokens && tokens[i]) + { + if (ft_strcmp(tokens[i], "\"\"") != 0 + && ft_strcmp(tokens[i], "''") != 0) + return (0); + i++; + } + return (1); +} + +void handle_normal_state(char input_char, t_Tokenizer *tk) +{ + if (input_char == '\'') + { + tk->state = SINGLE_QUOTE; + } + else if (input_char == '\"') + { + tk->state = DOUBLE_QUOTE; + } + else + { + tk->token[(tk->token_length)++] = input_char; + tk->symbol = true; + } +} + +void handle_double_quote_state(char input_char, t_Tokenizer *tk) +{ + if (input_char != '\"') + { + tk->token[(tk->token_length)++] = input_char; + if (input_char == '$') + { + tk->variable = 0; + } + if (is_simple_symbol(input_char) == true) + tk->symbol = false; + } + else + { + if (tk->token_length > 0 && tk->token[tk->token_length - 1] == ' ') + { + tk->token[(tk->token_length)++] = input_char; + } + else + { + tk->state = NORMAL; + tk->symbol = true; + } + } +} + +void handle_single_quote_state(char input_char, t_Tokenizer *tk) +{ + if (input_char != '\'') + { + tk->token[(tk->token_length)++] = input_char; + if (input_char == '$') + { + tk->variable = 1; + } + if (is_simple_symbol(input_char) == true) + { + tk->symbol = false; + } + } + else + { + if (tk->token_length > 0 && tk->token[tk->token_length - 1] == ' ') + { + tk->token[(tk->token_length)++] = input_char; + } + else + { + tk->state = NORMAL; + } + } +} + +char **handle_unclosed_quotes(char ***tokens, int token_pos) +{ + int i; + + i = 0; + if (tokens == NULL || *tokens == NULL) + { + return (NULL); + } + write(2, RED"Error: quote not closed\n"RST, 32); + if (token_pos > 0) + { + while (i < token_pos) + { + free((*tokens)[i]); + i++; + } + free(*tokens); + } + *tokens = NULL; + return (NULL); +} diff --git a/tokenize/tokenize.c b/tokenize/tokenize.c new file mode 100755 index 0000000..c416de4 --- /dev/null +++ b/tokenize/tokenize.c @@ -0,0 +1,112 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* tokenize.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/11/21 20:09:39 by fgras-ca #+# #+# */ +/* Updated: 2023/12/09 01:03:54 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +bool handle_quotes(char current_char, t_Tokenizer *tk) +{ + if ((tk->state == NORMAL && (current_char == '\'' || current_char == '\"')) + || (tk->state == SINGLE_QUOTE && current_char == '\'') + || (tk->state == DOUBLE_QUOTE && current_char == '\"')) + { + if (tk->state == NORMAL) + { + if (current_char == '\'') + { + tk->state = SINGLE_QUOTE; + } + else + { + tk->state = DOUBLE_QUOTE; + } + } + else + tk->state = NORMAL; + tk->input_pos++; + return (true); + } + return (false); +} + +void process_remaining_chars(char current_char, char *input, t_Tokenizer *tk) +{ + if (tk->state != NORMAL) + { + process_char(current_char, tk); + tk->input_pos++; + return ; + } + if (current_char == ' ' || current_char == '\t') + { + if (tk->token_length > 0) + { + add_token_to_list(tk); + } + handle_spaces_and_tabs(input, tk); + } + else if (is_special_symbol(current_char, input[tk->input_pos + 1])) + add_special_symbol(input, tk); + else + { + process_char(current_char, tk); + tk->variable = 0; + tk->input_pos++; + } +} + +void process_input_char(char *input, t_Tokenizer *tk) +{ + char current_char; + + current_char = input[tk->input_pos]; + if (!handle_quotes(current_char, tk)) + { + process_remaining_chars(current_char, input, tk); + } +} + +void tokenize_loop(char *input, t_Tokenizer *tk) +{ + while (input[tk->input_pos] != '\0') + { + process_input_char(input, tk); + } + if (tk->token_length > 0) + { + add_token_to_list(tk); + } +} + +char **tokenize_and_parse_input(char *input, t_minishell *shell, int fd) +{ + char **result; + + if (is_only_spaces(input)) + return (NULL); + init_vars(shell->tokenizer, input); + tokenize_loop(input, shell->tokenizer); + if (shell->tokenizer->state == SINGLE_QUOTE + || shell->tokenizer->state == DOUBLE_QUOTE) + { + result = handle_unclosed_quotes(&shell->tokenizer->tokens, + shell->tokenizer->token_pos); + free(shell->tokenizer->token); + return (result); + } + add_token_to_list(shell->tokenizer); + if (shell->tokenizer->tokens != NULL) + shell->tokenizer->tokens[shell->tokenizer->token_pos] = NULL; + parse_tokens(shell->tokenizer->tokens, shell, fd); + free(shell->tokenizer->token); + free_tokens(shell->tokenizer->tokens); + return (NULL); +} diff --git a/tokenize/tokenize_symbol.c b/tokenize/tokenize_symbol.c new file mode 100755 index 0000000..0ffc145 --- /dev/null +++ b/tokenize/tokenize_symbol.c @@ -0,0 +1,89 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* tokenize_symbol.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/12/03 17:34:50 by fgras-ca #+# #+# */ +/* Updated: 2023/12/07 16:19:24 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +void handle_spaces_and_tabs(char *input, t_Tokenizer *tk) +{ + while (input[tk->input_pos] == ' ' || input[tk->input_pos] == '\t') + { + tk->input_pos++; + } +} + +void add_special_symbol(char *input, t_Tokenizer *tk) +{ + if (tk->token_length > 0) + { + add_token_to_list(tk); + } + tk->token[0] = input[tk->input_pos++]; + tk->token_length = 1; + if ((tk->token[0] == '>' && input[tk->input_pos] == '>') + || (tk->token[0] == '<' && input[tk->input_pos] == '<')) + { + tk->token[tk->token_length++] = input[tk->input_pos++]; + } + tk->token[tk->token_length] = '\0'; + add_token_to_list(tk); +} + +void handle_empty_quotes(char *input, t_Tokenizer *tk) +{ + char quote_type; + int start_pos; + int i; + + quote_type = input[tk->input_pos]; + start_pos = tk->input_pos; + tk->input_pos++; + while (input[tk->input_pos] != quote_type && input[tk->input_pos] != '\0') + { + tk->input_pos++; + } + if (input[tk->input_pos] == quote_type) + { + if (tk->input_pos - start_pos > 1) + { + i = start_pos + 1; + while (i < tk->input_pos) + { + tk->token[tk->token_length++] = input[i]; + i++; + } + add_token_to_list(tk); + } + tk->input_pos++; + } +} + +bool is_special_symbol(char c, char next_c) +{ + if (c == '|' || c == '<' || c == '>') + { + return (true); + } + if ((c == '>' && next_c == '>') || (c == '<' && next_c == '<')) + { + return (true); + } + return (false); +} + +bool is_simple_symbol(char c) +{ + if (c == '|' || c == '<' || c == '>') + { + return (true); + } + return (false); +} diff --git a/tokenize/tokenize_utils.c b/tokenize/tokenize_utils.c new file mode 100755 index 0000000..91b4cb5 --- /dev/null +++ b/tokenize/tokenize_utils.c @@ -0,0 +1,87 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* tokenize_utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/12/01 17:41:31 by fgras-ca #+# #+# */ +/* Updated: 2023/12/10 11:23:56 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +void free_tokens(char **tokens) +{ + int i; + + if (tokens != NULL) + { + i = 0; + while (tokens[i] != NULL) + { + free(tokens[i]); + i++; + } + free(tokens); + } +} + +void add_token_to_list(t_Tokenizer *tk) +{ + char *token_to_add; + + if (tk->token_length > 0) + { + tk->token[tk->token_length] = '\0'; + token_to_add = strdup(tk->token); + if (token_to_add != NULL) + { + tk->tokens[tk->token_pos++] = token_to_add; + } + tk->token_length = 0; + tk->within_single_quotes = false; + tk->within_double_quotes = false; + } + if (tk->token != NULL) + { + free(tk->token); + } + tk->token = malloc(1000); + if (tk->token != NULL) + { + ft_memset(tk->token, 0, 1000); + } +} + +void process_char(char input_char, t_Tokenizer *tk) +{ + if (tk->state == NORMAL) + { + handle_normal_state(input_char, tk); + } + else if (tk->state == SINGLE_QUOTE) + { + handle_single_quote_state(input_char, tk); + } + else if (tk->state == DOUBLE_QUOTE) + { + handle_double_quote_state(input_char, tk); + } +} + +void init_vars(t_Tokenizer *tk, char *input) +{ + tk->state = NORMAL; + tk->tokens = malloc(MAX_ARGS * sizeof(char *)); + tk->token = malloc(ft_strlen(input) + 1); + tk->token_length = 0; + tk->input_pos = 0; + tk->token_pos = 0; + if (!(tk->tokens) || !(tk->token)) + { + write(STDERR_FILENO, "Minishell: allocation error\n", 29); + exit(EXIT_FAILURE); + } +} diff --git a/utils/utils.c b/utils/utils.c new file mode 100755 index 0000000..bb9b9b6 --- /dev/null +++ b/utils/utils.c @@ -0,0 +1,49 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/12/01 17:49:16 by fgras-ca #+# #+# */ +/* Updated: 2023/12/07 16:00:03 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../minishell.h" + +int is_only_spaces(const char *str) +{ + while (*str) + { + if (*str != ' ' && *str != '\t') + return (0); + str++; + } + return (1); +} + +char *get_env_value(const char *key, char **environ) +{ + int i; + char *entry; + char *delim; + + if (!key || !environ) + return (NULL); + i = 0; + entry = environ[i]; + while (entry != NULL) + { + delim = strchr(entry, '='); + if (delim != NULL) + { + if (ft_strncmp(entry, key, delim - entry) + == 0 && ft_strlen(key) == (size_t)(delim - entry)) + return (delim + 1); + } + i++; + entry = environ[i]; + } + return (NULL); +}