diff --git a/Makefile b/Makefile index 611e1de..2fe1de8 100644 --- a/Makefile +++ b/Makefile @@ -2,19 +2,77 @@ # VARIABLE # ######################################################################################################################## -SRCS := main.c +SRCS := backslash.c \ + expand_var_utils.c \ + expand_var_utils2.c \ + init.c \ + main.c \ + parser_utils.c \ + redir.c \ + split.c \ + utils.c \ + expand_var.c \ + format_redir.c \ + init_utils.c \ + init_utils2.c \ + parser.c \ + pre_check.c \ + redir_utils.c \ + trim.c \ + trim_utils.c \ + free_func.c \ + header.c + +EXEC := built_cd.c \ + built_cd_back.c \ + built_exit.c \ + built_exit_free.c \ + built_export.c \ + built_export_add.c \ + built_export_checker.c \ + built_export_utils.c \ + exec_main.c \ + exec_error.c \ + exec_utils.c \ + built_echo.c \ + built_pwd.c \ + exec_redir.c \ + exec_wait.c \ + built_env.c \ + built_export_no_arg.c \ + built_unset.c \ + exec_redir_utils.c \ + heredoc.c \ + signals_main.c + + +VALGRIND := valgrind --suppressions=valgrind_ignore_leaks.txt --leak-check=full --show-leak-kinds=all\ + --track-fds=yes --show-mismatched-frees=yes --read-var-info=yes -s --trace-children=yes + +IGN_LEAK := valgrind_ignore_leaks.txt SRCS_D := srcs/ OBJS_D := objs/ -OBJS := $(SRCS:%.c=$(OBJS_D)%.o) +EXEC_D := exec/ -HEAD := includes/minishell.h +OBJS := $(SRCS:%.c=$(OBJS_D)%.o)\ + +OBJS_E := $(EXEC:%.c=$(OBJS_D)%.o)\ + +HEAD := includes/minishell.h \ + includes/parser.h \ + includes/builtins.h HEAD_D := . -CFLAGS := -Wall -Wextra -Werror -g3 +ifeq ($(shell uname), Darwin) +READLINE_DIR = $(shell brew --prefix readline) +endif +READLINE_LIB = -lreadline -lhistory -L $(READLINE_DIR)/lib + +CFLAGS := -Wall -Wextra -Werror -g3 -I$(READLINE_DIR)/include NAME := minishell @@ -35,22 +93,46 @@ LIB_A := $(addprefix $(LIB_D), $(LIB)) ######################################################################################################################## # RULES # ######################################################################################################################## - all : lib $(MAKE) $(NAME) lib : $(MAKE) -C $(LIB_D) -$(NAME) : $(OBJS_D) $(OBJS) $(LIB_A) $(HEAD) - $(CC) $(CFLAGS) -o $(NAME) $(OBJS) $(LIB_A) +leaks : all $(IGN_LEAK) + $(VALGRIND) ./$(NAME) + +$(NAME) : $(OBJS_D) $(OBJS) $(OBJS_E) $(LIB_A) $(HEAD) + $(CC) $(CFLAGS) -o $(NAME) $(OBJS) $(OBJS_E) $(LIB_A) -lm ${READLINE_LIB} $(OBJS) : $(OBJS_D)%.o: $(SRCS_D)%.c $(HEAD) $(LIB_H) - $(CC) $(CFLAGS) -I/usr/include -Isuper_libft -c $< -o $@ + $(CC) $(CFLAGS) -Isuper_libft -c $< -o $@ + +$(OBJS_E) : $(OBJS_D)%.o: $(EXEC_D)%.c $(HEAD) $(LIB_H) + $(CC) $(CFLAGS) -Isuper_libft -c $< -o $@ $(OBJS_D) : @mkdir -p $(OBJS_D) +$(IGN_LEAK) : + @echo "{" > $(IGN_LEAK) + @echo " leak readline" >> $(IGN_LEAK) + @echo " Memcheck:Leak" >> $(IGN_LEAK) + @echo " ..." >> $(IGN_LEAK) + @echo " fun:readline" >> $(IGN_LEAK) + @echo "}" >> $(IGN_LEAK) + @echo "{" >> $(IGN_LEAK) + @echo " leak add_history" >> $(IGN_LEAK) + @echo " Memcheck:Leak" >> $(IGN_LEAK) + @echo " ..." >> $(IGN_LEAK) + @echo " fun:add_history" >> $(IGN_LEAK) + @echo "}" >> $(IGN_LEAK) + @echo "{" >> $(IGN_LEAK) + @echo " leak readline_internal_char" >> $(IGN_LEAK) + @echo " Memcheck:Leak" >> $(IGN_LEAK) + @echo " ..." >> $(IGN_LEAK) + @echo " fun:readline_internal_char" >> $(IGN_LEAK) + @echo "}" >> $(IGN_LEAK) ######################################################################################################################## # COMMANDS # ######################################################################################################################## @@ -62,7 +144,8 @@ clean : fclean : clean $(RM) $(NAME) $(NAME_B) $(MAKE) fclean -C super_libft + $(RM) $(IGN_LEAK) re : fclean all -.PHONY: all clean fclean re lib \ No newline at end of file +.PHONY: all clean fclean re lib diff --git a/data/header2.txt b/data/header2.txt new file mode 100644 index 0000000..e9350a6 --- /dev/null +++ b/data/header2.txt @@ -0,0 +1,6 @@ + __ ____ _ _________ + / |/ (_)___ (_)___ ___ ____ ____ / __/ __( ) + / /|_/ / / __ \/ / __ `__ \/ __ \/ __ \/ /_/ /_ |/ + / / / / / / / / / / / / / / /_/ / / / / __/ __/ +/_/ /_/_/_/ /_/_/_/ /_/ /_/\____/_/ /_/_/ /_/ +by Grebrune & Beroy \ No newline at end of file diff --git a/data/tmp b/data/tmp new file mode 100644 index 0000000..e69de29 diff --git a/exec/built_cd.c b/exec/built_cd.c new file mode 100644 index 0000000..64b7bd1 --- /dev/null +++ b/exec/built_cd.c @@ -0,0 +1,108 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* built_cd.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: grebrune +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/14 15:49:11 by grebrune #+# #+# */ +/* Updated: 2024/07/08 20:13:12 by grebrune ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/minishell.h" + +int cd_error(t_head *head) +{ + if (head->cmd->next || (head->cmd->arg[1] && head->cmd->arg[1][0] == 0)) + return (1); + if (head->cmd->arg[1] && head->cmd->arg[2]) + return (write(2, "bash: cd: too many arguments\n", 29), g_error = 1, 1); + return (0); +} + +void cd_rep_or_new(t_head *head, char *n_pwd, char *old_pwd) +{ + if (replace_value(head, n_pwd, "PWD")) + { + new_pwd(head, n_pwd, "PWD"); + free(n_pwd); + } + if (replace_value(head, old_pwd, "OLDPWD")) + { + new_pwd(head, old_pwd, "OLDPWD"); + free(old_pwd); + } +} + +int ft_cd(t_head *head) +{ + int err; + char *new; + char *old; + + old = NULL; + if (cd_error(head)) + return (1); + new = cd_relative(head); + if (!new) + return (2); + err = get_path(&old); + if (err == 2) + return (2); + err = chdir(new); + if (err != 0) + return (cd_chdir_error(head, old, new), 1); + cd_rep_or_new(head, new, old); + return (0); +} + +char *cd_relative(t_head *head) +{ + char *new; + + new = NULL; + if (!head->cmd->arg[1]) + return (cd_find_var(head, "HOME")); + if (0 == ft_strcmp(head->cmd->arg[1], "../") + || 0 == ft_strcmp(head->cmd->arg[1], "..")) + return (cd_back_trim()); + if (0 == ft_strcmp(head->cmd->arg[1], "~/") + || 0 == ft_strcmp(head->cmd->arg[1], "~")) + return (cd_tild_trim(head)); + if (0 == ft_strcmp(head->cmd->arg[1], "-")) + return (cd_find_var(head, "OLDPWD")); + if (!ft_strncmp(head->cmd->arg[1], "~/", 2)) + return (cat_of_tild(head, head->cmd->arg[1])); + if (!ft_strncmp(head->cmd->arg[1], "/home", 5)) + return (ft_strdup(head->cmd->arg[1])); + if (get_path(&new) == 2) + return (NULL); + new = cd_cat_backslash(new, head->cmd->arg[1]); + if (!new) + return (write(2, "Crash of Malloc\n", 16), NULL); + return (new); +} + +char *cd_find_var(t_head *head, char *name) +{ + t_env *env; + char *str; + + str = NULL; + env = head->env; + while (env) + { + if (ft_strcmp(env->name, name) == 0) + { + str = ft_strdup(env->value); + if (!str) + return (write(2, "Crash of Malloc\n", 16), NULL); + break ; + } + env = env->next; + } + if (!str) + return (cd_not_found(name), NULL); + return (str); +} diff --git a/exec/built_cd_back.c b/exec/built_cd_back.c new file mode 100644 index 0000000..009982a --- /dev/null +++ b/exec/built_cd_back.c @@ -0,0 +1,102 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* built_cd_back.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: grebrune +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/21 14:35:38 by grebrune #+# #+# */ +/* Updated: 2024/07/08 20:13:12 by grebrune ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/minishell.h" + +char *cd_tild_trim(t_head *head) +{ + char *pwd; + char *new; + + pwd = cd_find_var(head, "USER"); + if (!pwd) + return (NULL); + new = ft_strjoin("/home/", pwd); + if (!new) + return (free(pwd), write(2, "Crash of Malloc\n", 16), NULL); + return (free(pwd), new); +} + +char *cd_back_trim(void) +{ + char *pwd; + char *new; + int i; + int x; + + i = 0; + pwd = NULL; + if (get_path(&pwd) == 2) + return (NULL); + while (pwd && pwd[i]) + i++; + while (pwd && pwd[i] != '/') + i--; + new = malloc(sizeof(char) * (i + 1)); + if (!new) + return (free(pwd), write(2, "Crash of Malloc\n", 16), NULL); + x = 0; + while (x < i) + { + new[x] = pwd[x]; + x++; + } + new[x] = 0; + return (free(pwd), new); +} + +void cd_not_found(char *name) +{ + write(2, "bash: cd: ", 10); + write(2, name, ft_strlen(name)); + write(2, " not set\n", 9); +} + +void cd_chdir_error(t_head *head, char *old_pwd, char *new_pwd) +{ + DIR *ptr_dir; + + g_error = 1; + ptr_dir = opendir(head->cmd->arg[1]); + perror("bash: cd"); + closedir(ptr_dir); + free(old_pwd); + free(new_pwd); +} + +char *cd_cat_backslash(char *path, char *dir) +{ + char *dest; + size_t i; + size_t x; + + dest = ft_calloc(sizeof (char), (ft_strlen(dir) + ft_strlen(path) + 2)); + if (!dest) + return (NULL); + i = 0; + while (path && path[i]) + { + dest[i] = path[i]; + i++; + } + x = 0; + dest[i++] = '/'; + while (dir && dir[x]) + { + dest[i] = dir[x]; + i++; + x++; + } + dest[i] = '\0'; + free(path); + return (dest); +} diff --git a/exec/built_echo.c b/exec/built_echo.c new file mode 100644 index 0000000..951270f --- /dev/null +++ b/exec/built_echo.c @@ -0,0 +1,82 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* built_echo.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: grebrune +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/14 15:47:13 by grebrune #+# #+# */ +/* Updated: 2024/06/28 11:21:13 by grebrune ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/minishell.h" + +int echo_newline(char *str) +{ + size_t i; + + i = 0; + while (str && str[i]) + { + if (i == 0 && str[i] == '-') + i++; + else if (i != 0 && str[i] == 'n') + i++; + else + return (0); + } + if (i != 0) + return (1); + return (0); +} + +void echo_pipe(t_head *head, t_cmd *copy) +{ + char *str; + + if (copy->prev) + { + str = get_next_line(0); + while (str) + { + free(str); + str = get_next_line(0); + } + } + write(1, "\n", 1); + free_fnp(head, head->fnp); + ft_free_all(head); + exit (0); +} + +void ft_echo(t_head *head, t_cmd *copy) +{ + int i; + int n; + + i = 1; + n = 0; + if (!copy->arg[1]) + echo_pipe(head, copy); + while (echo_newline(copy->arg[i])) + { + i++; + n++; + } + print_tab(head, copy->arg, i, n); +} + +void print_tab(t_head *head, char **arg, int i, int n) +{ + while (arg[i]) + { + ft_putstr(arg[i]); + i++; + if (arg[i]) + write(1, " ", 1); + } + if (n == 0) + printf("\n"); + exit_free(head, 0); +} diff --git a/exec/built_env.c b/exec/built_env.c new file mode 100644 index 0000000..89cf769 --- /dev/null +++ b/exec/built_env.c @@ -0,0 +1,53 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* built_env.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: grebrune +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/14 16:06:10 by grebrune #+# #+# */ +/* Updated: 2024/06/24 16:09:22 by grebrune ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/minishell.h" + +void ft_env(t_head *head) +{ + t_env *copy; + int i; + + if (!head->env) + exit_free(head, 0); + copy = head->env; + i = checker_env(head->cmd->arg); + if (i != 0) + { + write(2, "env: '", 6); + write(2, head->cmd->arg[i], ft_strlen(head->cmd->arg[i])); + write(2, "’: No such file or directory\n", 31); + exit_free(head, 0); + } + while (copy && copy->next) + { + printf("%s=%s\n", copy->name, copy->value); + copy = copy->next; + } + if (copy) + printf("%s=%s\n", copy->name, copy->value); + exit_free(head, 0); +} + +int checker_env(char **arg) +{ + int i; + + i = 0; + while (arg && arg[i]) + { + if (ft_strcmp(arg[i], "env")) + return (i); + i++; + } + return (0); +} diff --git a/exec/built_exit.c b/exec/built_exit.c new file mode 100644 index 0000000..d1becf0 --- /dev/null +++ b/exec/built_exit.c @@ -0,0 +1,77 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* built_exit.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: grebrune +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/05/13 17:28:49 by grebrune #+# #+# */ +/* Updated: 2024/07/02 15:26:09 by grebrune ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/minishell.h" + +void ft_exit(t_head *head) +{ + t_cmd *copy; + + if (!head->cmd->next) + write(2, "exit\n", 5); + if (!head->cmd->arg[1]) + { + exit_free(head, g_error); + return ; + } + copy = head->cmd; + if (ft_strnum(copy->arg[1])) + { + if (is_num(head)) + return ; + exit_free(head, 1); + return ; + } + exit_write(copy->arg[1]); + exit_free(head, 2); +} + +void exit_write(char *arg) +{ + write(2, "bash: exit: ", 12); + write(2, arg, ft_strlen(arg)); + write(2, ": numeric argument required\n", 28); +} + +int ft_strnum(char *str) +{ + int i; + + i = 0; + if (!str || (str && !str[0])) + return (0); + if (str[i] == '+' || str[i] == '-') + i++; + while (str && str[i]) + { + if (!(str[i] >= 48 && str[i] <= 57)) + return (0); + i++; + } + return (1); +} + +int is_num(t_head *head) +{ + if (head->cmd->arg[2]) + { + write(2, "bash: exit: too many arguments\n", 31); + g_error = 1; + return (1); + } + else + { + g_error = ft_atoi(head->cmd->arg[1]) % 256; + exit_free(head, g_error); + return (0); + } +} diff --git a/exec/built_exit_free.c b/exec/built_exit_free.c new file mode 100644 index 0000000..7c90b29 --- /dev/null +++ b/exec/built_exit_free.c @@ -0,0 +1,86 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* built_exit_free.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: grebrune +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/21 17:13:12 by grebrune #+# #+# */ +/* Updated: 2024/07/08 18:40:36 by grebrune ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/minishell.h" + +void exit_free(t_head*head, int status) +{ + free_fnp(head, head->fnp); + ft_free_all(head); + exit (status); +} + +void new_pwd(t_head *head, char *value, char *name) +{ + t_env *new; + t_env *copy; + + copy = head->env; + new = ft_calloc(1, sizeof(t_env)); + if (!new) + return ; + while (copy && copy->next) + copy = copy->next; + new_var_bis(copy, head, new); + new->next = NULL; + new->name = ft_strdup(name); + if (!new->name) + return ; + new->value = ft_strdup(value); + if (!new->value) + return ; + return ; +} + +int replace_value(t_head *head, char *value, char *replace) +{ + t_env *copy; + + copy = head->env; + while (copy) + { + if (ft_strcmp(copy->name, replace) == 0) + { + free(copy->value); + copy->value = value; + return (0); + } + copy = copy->next; + } + return (1); +} + +char *cat_of_tild(t_head *head, char *str) +{ + size_t i; + size_t x; + char *new; + char *home; + + i = 0; + home = cd_find_var(head, "HOME"); + if (!home) + return (NULL); + i = ft_strlen(str) - 1; + x = ft_strlen(home); + new = ft_calloc(sizeof (char), x + i + 1); + if (!new) + return (free(home), NULL); + i = -1; + while (home[++i]) + new[i] = home[i]; + x = 1; + while (str[x]) + new[i++] = str[x++]; + new[i] = '\0'; + return (free(home), new); +} diff --git a/exec/built_export.c b/exec/built_export.c new file mode 100644 index 0000000..186faab --- /dev/null +++ b/exec/built_export.c @@ -0,0 +1,118 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* built_export.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: grebrune +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/14 15:51:12 by grebrune #+# #+# */ +/* Updated: 2024/06/28 15:48:54 by grebrune ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/minishell.h" + +int ft_export(t_head *head) +{ + t_env *c_env; + size_t i; + + c_env = head->env; + if (head->cmd->arg[1] == NULL) + return (ex_no_args(head)); + if (head->cmd->next != NULL) + return (3); + i = 1; + while (head->cmd->arg[i]) + { + if (export_bis(head, c_env, i)) + return (2); + i++; + } + return (0); +} + +int export_bis(t_head *head, t_env *c_env, size_t i) +{ + if (check_name(head, head->cmd->arg[i], c_env)) + return (g_error = 1, 0); + if (no_plus(head->cmd->arg[i])) + { + if (export_search_env(c_env, head->cmd->arg[i]) == 0) + { + if (2 == new_var(head, head->cmd->arg[i])) + return (write(2, "Crash of Malloc\n", 16), 2); + } + else + return (1); + } + return (0); +} + +int ft_strcmp_until(char *s1, const char *s2) +{ + size_t i; + + i = 0; + while (s1[i] != 0 || s2[i] != 0) + { + if (s1[i] == 0 && s2[i] == '+') + return (0); + if (s2[i] == '=' || s1[i] == '=') + return (0); + if (s1[i] != s2[i]) + return (((unsigned char *)s1)[i] - ((unsigned char *)s2)[i]); + i++; + } + return (0); +} + +char *replace_var_until(char *arg, char *result) +{ + size_t z; + size_t i; + char *ret; + + free(arg); + z = ft_strlen_until(result); + i = 0; + if (z == ft_strlen(result) && ft_strlen(arg) == 0) + return (ft_strdup("\0")); + while (result && result[z + 1 + i]) + i++; + ret = malloc(sizeof(char) * (i + 1)); + if (!ret) + return (NULL); + i = 0; + while (result && result[z + 1 + i]) + { + ret[i] = result[z + 1 + i]; + i++; + } + ret[i] = '\0'; + return (ret); +} + +int new_var(t_head *head, char *name) +{ + t_env *new; + t_env *copy; + + copy = head->env; + if (check_equal(name)) + return (g_error = 0, 0); + new = ft_calloc(1, sizeof(t_env)); + if (!new) + return (2); + while (copy && copy->next) + copy = copy->next; + new_var_bis(copy, head, new); + new->next = NULL; + new->name = dup_until(name); + if (!new->name) + return (2); + new->value = dup_if(name); + if (!new->value) + return (2); + return (0); +} diff --git a/exec/built_export_add.c b/exec/built_export_add.c new file mode 100644 index 0000000..45be1ac --- /dev/null +++ b/exec/built_export_add.c @@ -0,0 +1,93 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* built_export_add.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: grebrune +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/19 20:11:01 by grebrune #+# #+# */ +/* Updated: 2024/06/28 15:47:07 by grebrune ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/minishell.h" + +int export_search_env(t_env *c_env, char *name) +{ + while (c_env) + { + if (0 == ft_strcmp_until(c_env->name, name)) + { + c_env->value = replace_var_until(c_env->value, name); + if (!c_env->value) + return (write(2, "Crash of Malloc\n", 16), 2); + return (1); + } + c_env = c_env->next; + } + return (0); +} + +void error_handle(char *str) +{ + write(2, "bash: export: `", 15); + write(2, str, ft_strlen(str)); + write(2, "': not a valid identifier\n", 26); +} + +char *strcat_until(char *val, char *name) +{ + int i; + int x; + char *new_val; + + i = 0; + while (name && name[i]) + i++; + i += ft_strlen(val); + i -= ft_strlen_until(name); + new_val = malloc(sizeof(char) * (i + 1)); + if (!new_val) + return (NULL); + i = -1; + while (val && val[++i]) + new_val[i] = val[i]; + x = ft_strlen_until(name); + x++; + while (name && name[x]) + new_val[i++] = name[x++]; + new_val[i] = 0; + return (free(val), new_val); +} + +int add_var(t_head *head, char *name, t_env *c_env) +{ + while (c_env) + { + if (0 == ft_strcmp_until(c_env->name, name)) + { + c_env->value = strcat_until(c_env->value, name); + if (!c_env->value) + return (write(2, "Crash of Malloc\n", 16), 2); + return (1); + } + c_env = c_env->next; + } + if (new_var(head, name)) + return (write(2, "Crash of Malloc\n", 16), 2); + return (0); +} + +void new_var_bis(t_env *copy, t_head *head, t_env *new) +{ + if (copy) + { + copy->next = new; + new->prev = copy; + } + else + { + head->env = new; + new->prev = NULL; + } +} diff --git a/exec/built_export_checker.c b/exec/built_export_checker.c new file mode 100644 index 0000000..a19cbc0 --- /dev/null +++ b/exec/built_export_checker.c @@ -0,0 +1,67 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* built_export_checker.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: grebrune +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/21 16:32:41 by grebrune #+# #+# */ +/* Updated: 2024/07/09 18:36:17 by grebrune ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/minishell.h" + +int check_name_errors(char *name) +{ + if (ft_strcmp("", name) == 0) + return (write(2, "bash: export: `': not a valid identifier\n", 41), 1); + if (ft_strcmp("=", name) == 0) + return (g_error = 1, write(2, "bash: export: " + "`=': not a valid identifier\n", 42), 1); + if (ft_strcmp("+=", name) == 0) + return (g_error = 1, write(2, "bash: export: " + "`+=': not a valid identifier\n", 43), 1); + if (ft_isdigit(name[0])) + return (error_handle(name), 1); + if (name[0] == '=') + { + write(2, "bash: export: '", 15); + write(2, name, ft_strlen(name)); + write(2, "': not a valid identifier\n", 26); + return (g_error = 1, 1); + } + return (0); +} + +int check_name(t_head *head, char *name, t_env *c_env) +{ + int i; + + i = 0; + if (check_name_errors(name)) + return (1); + while (name[i] && name[i] != '=') + { + if (name[i] == '+' && name[i + 1] == '=') + return (add_var(head, name, c_env), 0); + if (!ft_isalnum(name[i]) && name[i] != '_') + return (error_handle(name), 1); + i++; + } + return (0); +} + +int no_plus(char *name) +{ + size_t i; + + i = 0; + while (name && name[i] && name[i] != '=') + { + if (name[i] == '+') + return (0); + i++; + } + return (1); +} diff --git a/exec/built_export_no_arg.c b/exec/built_export_no_arg.c new file mode 100644 index 0000000..c19d00f --- /dev/null +++ b/exec/built_export_no_arg.c @@ -0,0 +1,102 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* built_export_no_arg.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: grebrune +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/05/13 15:09:17 by grebrune #+# #+# */ +/* Updated: 2024/06/28 11:38:35 by grebrune ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/builtins.h" + +int ex_no_args(t_head *head) +{ + char **tab; + t_env *copy; + + if (!head->env) + exit_free(head, 0); + copy = head->env; + tab = env_to_tab(copy); + if (!tab) + { + write(2, "Crash of Malloc\n", 16); + exit_free(head, 0); + } + swap_this_tab(tab); + printf_tab(tab); + free_tab(tab); + close_pipe(); + return (exit_free(head, 0), 0); +} + +char **env_to_tab(t_env *copy) +{ + char **tab; + size_t x; + + tab = malloc((sizeof (char *)) * (envlen(copy) + 2)); + if (!tab) + return (NULL); + x = 0; + while (copy) + { + tab[x] = join_equal(copy->name, copy->value); + if (!tab[x]) + return (ft_splitdestroy(tab), NULL); + x++; + copy = copy->next; + } + tab[x] = NULL; + return (tab); +} + +void printf_tab(char **tab) +{ + size_t x; + + x = 0; + while (tab[x] != NULL) + { + if (ft_strncmp("_=\"/home", tab[x], 8) != 0) + printf("declare -x %s\n", tab[x]); + x++; + } +} + +void swap_this_tab(char **tab) +{ + int x; + char *tmp; + + x = 0; + while (tab[x] && tab[x + 1]) + { + if (0 < ft_strcmp(tab[x], tab[x + 1])) + { + tmp = tab[x]; + tab[x] = tab[x + 1]; + tab[x + 1] = tmp; + x = 0; + } + else + x++; + } +} + +char *join_equal(char *name, char *val) +{ + char *n_w_e; + char *v_w_e; + char *join; + + n_w_e = ft_strjoin(name, "=\""); + v_w_e = ft_strjoin(val, "\""); + join = ft_strjoin(n_w_e, v_w_e); + free(n_w_e); + free(v_w_e); + return (join); +} diff --git a/exec/built_export_utils.c b/exec/built_export_utils.c new file mode 100644 index 0000000..2b38255 --- /dev/null +++ b/exec/built_export_utils.c @@ -0,0 +1,81 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* built_export_utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: grebrune +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/12 13:46:00 by grebrune #+# #+# */ +/* Updated: 2024/06/20 12:29:16 by grebrune ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/minishell.h" + +int check_equal(char *str) +{ + int i; + + i = 0; + while (str && str[i]) + { + if (str[i] == '=') + return (0); + i++; + } + return (1); +} + +char *dup_until(char *str) +{ + size_t size; + size_t i; + char *ptr; + + size = 0; + while (str && str[size] && str[size] != '=' && str[size] != '+') + size++; + ptr = malloc((size + 1) * sizeof(char)); + if (ptr == NULL) + return (ptr); + i = 0; + while (i < size) + { + ptr[i] = str[i]; + i++; + } + ptr[i] = 0; + return (ptr); +} + +char *dup_if(char *name) +{ + size_t i; + + i = 0; + while (name && name[i] && name[i] != '=') + i++; + if (!(name[i] == '=' && name[i + 1] != '\0')) + return (ft_strdup("\0")); + return (ft_strdup(&name[i + 1])); +} + +int ft_strlen_until(char *str) +{ + int i; + + i = 0; + while (str && str[i] && str[i] != '=') + i++; + return (i); +} + +void free_tab(char **tab) +{ + int x; + + x = 0; + while (tab[x]) + ft_free(tab[x++]); + ft_free(tab); +} diff --git a/exec/built_pwd.c b/exec/built_pwd.c new file mode 100644 index 0000000..2a2509d --- /dev/null +++ b/exec/built_pwd.c @@ -0,0 +1,48 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* built_pwd.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: grebrune +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/14 15:48:06 by grebrune #+# #+# */ +/* Updated: 2024/07/09 12:50:59 by grebrune ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/minishell.h" + +void ft_pwd(t_head *head) +{ + int err; + char *str; + + str = NULL; + err = get_path(&str); + if (err == 2) + exit_free(head, 1); + if (str) + printf("%s\n", str); + free(str); + exit_free(head, 0); +} + +int get_path(char **str) +{ + size_t size; + + size = 10; + while (!*(str)) + { + *str = getcwd(*(str), size); + if (!*(str)) + { + free(*(str)); + *(str) = NULL; + if (errno != ERANGE) + return (perror("bash: getcwd"), 2); + } + size += 10; + } + return (0); +} diff --git a/exec/built_unset.c b/exec/built_unset.c new file mode 100644 index 0000000..409ef35 --- /dev/null +++ b/exec/built_unset.c @@ -0,0 +1,61 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* built_unset.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: grebrune +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/14 16:03:36 by grebrune #+# #+# */ +/* Updated: 2024/07/09 16:15:07 by grebrune ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/minishell.h" + +void ft_unset(t_head *head) +{ + int i; + + if (head->cmd->next || !head->cmd->arg[1]) + return ; + i = 1; + while (head->cmd->arg[i]) + { + rem_env(&head->env, head->cmd->arg[i], &ft_strcmp); + i++; + } +} + +void free_rem(t_env *remove) +{ + ft_free(remove->name); + ft_free(remove->value); + ft_free(remove); +} + +void rem_env(t_env **env, void *ref, int (*cmp)(char *, const char *)) +{ + t_env *tmp; + + tmp = *env; + if ((*cmp)((*env)->name, ref) == 0) + { + *env = (*env)->next; + (*env)->prev = NULL; + return (free_rem(tmp), (void)0); + } + while (tmp) + { + if ((*cmp)(tmp->name, ref) == 0) + { + if (tmp->prev) + tmp->prev->next = tmp->next; + if (tmp->next) + tmp->next->prev = tmp->prev; + return (free_rem(tmp), (void)0); + } + if (tmp->next == NULL) + break ; + tmp = tmp->next; + } +} diff --git a/exec/exec_error.c b/exec/exec_error.c new file mode 100644 index 0000000..59852e3 --- /dev/null +++ b/exec/exec_error.c @@ -0,0 +1,29 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* exec_error.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: grebrune +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/07/02 19:44:43 by grebrune #+# #+# */ +/* Updated: 2024/07/09 01:14:30 by grebrune ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/minishell.h" + +void exec_error_exit(char **arg, char **env, char **path) +{ + write(2, "bash: ", 6); + perror(arg[0]); + if (env) + free_tab(env); + if (path) + free_tab(path); + if (arg) + free_tab(arg); + if (errno == EACCES) + exit (126); + else + exit (127); +} diff --git a/exec/exec_main.c b/exec/exec_main.c new file mode 100644 index 0000000..79de611 --- /dev/null +++ b/exec/exec_main.c @@ -0,0 +1,122 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* exec_main.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: grebrune +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/22 16:34:19 by grebrune #+# #+# */ +/* Updated: 2024/07/09 01:23:33 by grebrune ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/builtins.h" + +void exec_shell(char **arg, char *str, char **env) +{ + char **path; + int i; + char *cmd; + + path = ft_split(str, ':'); + ft_free(str); + if (!path) + exec_error_exit(arg, env, path); + i = 0; + while (path[i]) + { + cmd = join_with_char(path[i], arg[0], '/'); + if (!(access(cmd, F_OK)) && !(access(cmd, X_OK))) + execve(cmd, arg, env); + i++; + ft_free(cmd); + } + if (!(access(arg[0], F_OK)) && !(access(arg[0], X_OK))) + execve(arg[0], arg, env); + exec_error_exit(arg, env, path); +} + +int no_fork_cmd(t_head *head, t_cmd *copy, char *str) +{ + if (!str || str[0] == 0) + return (0); + if (ft_strcmp(str, "cd") == 0) + return (ft_cd(head), 0); + if ((ft_strcmp(str, "export") == 0) && copy->arg[1] != NULL) + return (ft_export(head), 0); + if (ft_strcmp(str, "unset") == 0) + return (ft_unset(head), 0); + if (ft_strcmp(str, "exit") == 0 && (!copy->next && !copy->prev)) + return (ft_exit(head), 0); + return (3); +} + +int exec_shell_malloc(t_head *head, t_cmd *copy, t_fnp *fnp) +{ + char **env; + char **tab; + char *path; + + env = make_env(head->env); + if (!env) + exit_free(head, 1); + tab = make_arg(copy); + if (!tab) + return (free_tab(env), exit_free(head, 1), 0); + path = find_path(head); + if (!path) + no_path_to_hapiness(head, env, tab, copy); + free_fnp(head, fnp); + ft_free_all(head); + exec_shell(tab, path, env); + return (0); +} + +int find_cmd(t_head *head, t_cmd *copy, t_fnp *fnp, int x) +{ + int fd[2]; + + if (no_fork_cmd(head, copy, copy->arg[0]) == 0) + return (fnp->pid[x] = 0, 0); + fnp->pid[x] = fork(); + if (fnp->pid[x] < 0) + return (write(2, "Crash of Fork\n", 14), exit_free(head, 0), 0); + if (fnp->pid[x] != 0) + return (0); + sig_main(head, 1); + if (redir_with_fd(fd, fnp->pipe, copy, x)) + return (close_pipe(), exit_free(head, 1), 2); + close_pipe(); + if (ft_strcmp(copy->arg[0], "echo") == 0) + return (ft_echo(head, copy), 1); + if (ft_strcmp(copy->arg[0], "env") == 0) + return (ft_env(head), 1); + if (ft_strcmp(copy->arg[0], "pwd") == 0) + return (ft_pwd(head), 1); + if (ft_strcmp(copy->arg[0], "export") == 0) + return (ft_export(head)); + if (ft_strcmp(copy->arg[0], "exit") == 0) + return (ft_exit(head), 0); + return (exec_shell_malloc(head, copy, fnp)); +} + +int executable(t_head *head) +{ + t_cmd *copy; + int x; + + x = 0; + malloc_fnp(head); + open_the_pipe(head->fnp->pipe, head); + copy = head->cmd; + while (copy != NULL) + { + find_cmd(head, copy, head->fnp, x); + copy = copy->next; + x++; + } + close_pipe(); + wait_for_all(head->fnp->pid, x); + free_fnp(head, head->fnp); + return (0); +} diff --git a/exec/exec_redir.c b/exec/exec_redir.c new file mode 100644 index 0000000..d7486c2 --- /dev/null +++ b/exec/exec_redir.c @@ -0,0 +1,90 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* exec_redir.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: grebrune +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/05/09 14:44:44 by grebrune #+# #+# */ +/* Updated: 2024/07/02 22:40:24 by grebrune ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/builtins.h" + +void fail_malloc(t_head *head, int **fd, size_t i) +{ + while (i-- > 0) + free(fd[i]); + free(head->fnp->pid); + free(head->fnp->pipe); + free(head->fnp); + ft_free_all(head); + exit(0); +} + +int open_the_pipe(int **pipe, t_head *head) +{ + size_t numb; + size_t i; + + numb = cmdlen(head->cmd); + if (numb == 1) + return (0); + i = 0; + while (i < numb) + { + pipe[i] = malloc(sizeof(int) * 2); + if (!pipe[i]) + return (fail_malloc(head, pipe, i), 1); + i++; + } + fill_pipe(numb, pipe, head); + return (0); +} + +int open_files(t_redir *redir, int *err_print) +{ + if (redir->type == 1) + redir->fd = open(redir->arg, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (redir->type == 2) + redir->fd = open(redir->arg, O_WRONLY | O_CREAT | O_APPEND, 0644); + if ((redir->type == 4 && redir->fd == -1) || redir->type == 3) + redir->fd = open(redir->arg, O_RDONLY); + if (redir->fd == -1) + { + if (*err_print == 0) + perror(redir->arg); + *err_print = 1; + return (2); + } + return (0); +} + +int open_redir(t_cmd *copy, int fd[2]) +{ + t_redir *parser; + t_cmd *c_cmd; + int err_print; + + fd[1] = 1; + fd[0] = 0; + c_cmd = copy; + err_print = 0; + while (c_cmd) + { + parser = c_cmd->redir; + while (parser) + { + if (open_files(parser, &err_print)) + return (2); + if (parser->type == 1 || parser->type == 2) + fd[1] = parser->fd; + if (parser->type == 3 || parser->type == 4) + fd[0] = parser->fd; + parser = parser->next; + } + c_cmd = c_cmd->next; + } + return (0); +} diff --git a/exec/exec_redir_utils.c b/exec/exec_redir_utils.c new file mode 100644 index 0000000..06b1085 --- /dev/null +++ b/exec/exec_redir_utils.c @@ -0,0 +1,94 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* exec_redir_utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: grebrune +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/12 13:57:10 by grebrune #+# #+# */ +/* Updated: 2024/07/08 17:31:01 by grebrune ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/minishell.h" + +int fill_pipe(size_t numb, int **fd, t_head *head) +{ + size_t i; + + i = 0; + while (i < numb - 1) + { + if (pipe(fd[i]) == -1) + { + perror("pipe"); + free_fnp(head, head->fnp); + ft_free_all(head); + exit (1); + } + i++; + } + fd[i][1] = 1; + return (0); +} + +void close_pipe(void) +{ + int i; + + i = 2; + while (++i < 1024) + close(i); +} + +int redir_with_fd(int fd[2], int **pipe, t_cmd *copy, int x) +{ + if (open_redir(copy, fd)) + return (2); + if (copy->prev) + fd[0] = pipe[x - 1][0]; + if (copy->next && !copy->redir) + fd[1] = pipe[x][1]; + if (fd[0] != 0 && (copy->prev || copy->redir)) + { + if (dup2(fd[0], STDIN_FILENO) == -1) + return (perror("dup2"), 2); + } + if (fd[1] != 1 && (copy->next || copy->redir)) + { + if (dup2(fd[1], STDOUT_FILENO) == -1) + return (perror("dup2"), 2); + } + return (0); +} + +void free_fnp(t_head *head, t_fnp *fnp) +{ + size_t nbr_pipe; + size_t i; + + i = 0; + nbr_pipe = cmdlen(head->cmd); + while (nbr_pipe != 1 && i < nbr_pipe) + { + free(fnp->pipe[i]); + i++; + } + free(head->fnp->pid); + free(head->fnp->pipe); + free(head->fnp); +} + +int malloc_fnp(t_head *head) +{ + head->fnp = malloc(sizeof(t_fnp)); + if (!head->fnp) + return (free_malloc_fnp(head, 0), 1); + head->fnp->pid = malloc(sizeof(int) * cmdlen(head->cmd)); + if (!head->fnp->pid) + return (free_malloc_fnp(head, 1), 1); + head->fnp->pipe = malloc(sizeof(int *) * cmdlen(head->cmd)); + if (!head->fnp->pipe) + return (free_malloc_fnp(head, 2), 1); + return (0); +} diff --git a/exec/exec_utils.c b/exec/exec_utils.c new file mode 100644 index 0000000..e4334db --- /dev/null +++ b/exec/exec_utils.c @@ -0,0 +1,117 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* exec_utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: grebrune +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/22 17:31:24 by grebrune #+# #+# */ +/* Updated: 2024/07/09 01:14:30 by grebrune ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/builtins.h" + +char *find_path(t_head *head) +{ + t_env *copy; + char *path; + + copy = head->env; + while (copy) + { + if (ft_strcmp("PATH", copy->name) == 0) + { + path = ft_strdup(copy->value); + return (path); + } + copy = copy->next; + } + return (NULL); +} + +char *join_with_char(char const *s1, char const *s2, char c) +{ + size_t len; + size_t i; + size_t j; + char *str; + + len = ft_strlen((char *)s1) + ft_strlen((char *)s2); + i = 0; + str = malloc (sizeof(char) * (len + 2)); + if (str == NULL) + return (str); + while (s1[i]) + { + str[i] = s1[i]; + i++; + } + str[i++] = c; + j = 0; + while (s2[j]) + { + str[i + j] = s2[j]; + j++; + } + str [i + j] = 0; + return (str); +} + +char **make_env(t_env *env) +{ + t_env *copy; + char **tab; + size_t size; + size_t i; + + size = envlen(env); + if (size == 0) + return (NULL); + tab = malloc(sizeof (char *) * (size + 1)); + if (tab == NULL) + return (NULL); + copy = env; + i = 0; + while (i < size) + { + tab[i] = join_with_char(copy->name, copy->value, '='); + if (!tab[i]) + return (ft_splitdestroy(tab), NULL); + i++; + copy = copy->next; + } + tab[i] = NULL; + return (tab); +} + +void no_path_to_hapiness(t_head *head, char **env, char **tab, t_cmd *copy) +{ + char *exec; + + exec = ft_strdup(copy->arg[0]); + if (!exec) + exec_error_exit(tab, env, NULL); + free_fnp(head, head->fnp); + ft_free_all(head); + if (!(access(exec, F_OK)) && !(access(exec, X_OK))) + execve(exec, tab, env); + perror(exec); + free_tab(env); + free_tab(tab); + ft_free(exec); + if (errno == EACCES) + exit (126); + else + exit (127); +} + +void free_malloc_fnp(t_head *head, int to_free) +{ + if (to_free > 1) + free(head->fnp->pid); + if (to_free > 0) + free(head->fnp); + ft_free_all(head); + exit (0); +} diff --git a/exec/exec_wait.c b/exec/exec_wait.c new file mode 100644 index 0000000..d556051 --- /dev/null +++ b/exec/exec_wait.c @@ -0,0 +1,94 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* exec_wait.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: grebrune +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/30 18:51:28 by grebrune #+# #+# */ +/* Updated: 2024/07/09 01:26:35 by grebrune ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/builtins.h" + +int wait_for_all(pid_t *pid, int x) +{ + int i; + int wstatus[2]; + int last; + + wstatus[1] = 0; + wstatus[0] = 0; + i = 0; + while (i < x) + { + last = waitpid(0, &wstatus[0], 0); + if (last != -1 && last == pid[x - 1]) + wstatus[1] = wstatus[0]; + i++; + } + if (WIFSIGNALED(wstatus[1]) && WCOREDUMP(wstatus[1])) + { + write(2, "Quit (core dumped)\n", 19); + g_error = 131; + } + else if (WIFSIGNALED(wstatus[1])) + return (write(2, "\n", 1), g_error = 130, 0); + if (WIFEXITED(wstatus[1]) && last != -1) + g_error = WEXITSTATUS(wstatus[1]); + return (0); +} + +size_t envlen(t_env *base) +{ + size_t size; + t_env *copy; + + copy = base; + size = 0; + while (copy) + { + size++; + copy = copy->next; + } + return (size); +} + +size_t cmdlen(t_cmd *base) +{ + size_t size; + t_cmd *copy; + + copy = base; + size = 0; + while (copy) + { + size++; + copy = copy->next; + } + return (size); +} + +char **make_arg(t_cmd *cmd) +{ + char **arg; + int x; + + x = 0; + while (cmd->arg && cmd->arg[x]) + x++; + arg = malloc(sizeof (char *) * (x + 1)); + if (arg == NULL) + return (NULL); + x = 0; + while (cmd->arg && cmd->arg[x]) + { + arg[x] = ft_strdup(cmd->arg[x]); + if (!arg[x]) + return (ft_splitdestroy(arg), NULL); + x++; + } + arg[x] = NULL; + return (arg); +} diff --git a/exec/heredoc.c b/exec/heredoc.c new file mode 100644 index 0000000..d9f00be --- /dev/null +++ b/exec/heredoc.c @@ -0,0 +1,110 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* heredoc.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: grebrune +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/17 17:45:32 by grebrune #+# #+# */ +/* Updated: 2024/07/08 18:37:36 by grebrune ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/minishell.h" + +char *replace_var_heredoc(char *str, t_head *head) +{ + int start; + int end; + char *value; + char *dup; + + start = find_var(str); + end = find_end_var(str, start); + value = var_value(str, start + 1, head->env); + if (value == NULL) + return (NULL); + dup = str_dup_var(str, start, end, value); + if (dup == NULL) + return (NULL); + return (dup); +} + +int expand_heredoc(char **str, t_head *head) +{ + while (find_var(*str) != -1) + { + *str = replace_var_heredoc(*str, head); + if (*str == NULL) + return (1); + } + return (0); +} + +int here_read_print(int fd, char *eof, t_cmd *copy, t_head *head) +{ + char *str; + + while (42) + { + str = readline(">> "); + if (!str) + return (free(str), close(fd), 0); + if (ft_strstr("^C", str) != NULL) + return (free(str), close(fd), 2); + if (ft_strcmp(str, eof) == 0) + return (free(str), close(fd), 0); + if (copy->redir->quote == 0) + { + if (expand_heredoc(&str, head) == 1) + return (-1); + } + write(fd, str, ft_strlen(str)); + write(fd, "\n", 1); + free(str); + } + return (close(fd), 0); +} + +int checker_heredoc(t_head *head, t_redir *c_redir, t_cmd *c_cmd) +{ + int fd[2]; + + if (!c_redir->arg || !c_redir->arg[0]) + return (write(2, "bash: syntax error "\ + "near unexpected token `newline'\n", 51), 0); + if (pipe(fd) == -1) + { + perror("pipe"); + exit_free(head, 1); + } + c_redir->fd = fd[0]; + if (here_read_print(fd[1], c_redir->arg, c_cmd, head)) + return (0); + return (1); +} + +int heredoc(t_head *head) +{ + t_redir *c_redir; + t_cmd *c_cmd; + + c_cmd = head->cmd; + while (c_cmd) + { + c_redir = head->cmd->redir; + while (c_redir) + { + if (c_redir->type == 4) + { + sig_main(head, 2); + if (checker_heredoc(head, c_redir, c_cmd) == 0) + return (0); + sig_main(head, 0); + } + c_redir = c_redir->next; + } + c_cmd = c_cmd->next; + } + return (1); +} diff --git a/exec/signals_main.c b/exec/signals_main.c new file mode 100644 index 0000000..f4d95ce --- /dev/null +++ b/exec/signals_main.c @@ -0,0 +1,80 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* signals_main.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: grebrune +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/20 17:53:49 by grebrune #+# #+# */ +/* Updated: 2024/07/02 21:24:04 by grebrune ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/minishell.h" + +void sig(int sig) +{ + if (sig == SIGINT) + { + g_error = 130; + write(2, "\n", 1); + rl_on_new_line(); + rl_replace_line("", 0); + rl_redisplay(); + } +} + +void sig_child(int sig) +{ + if (sig == SIGPIPE) + { + rl_on_new_line(); + rl_replace_line("", 0); + } + if (sig == SIGINT) + { + g_error = 130; + write(2, "\n", 1); + } + if (sig == SIGQUIT) + { + g_error = 131; + write(2, "Quit (core dumped)\n", 19); + rl_on_new_line(); + rl_replace_line("", 0); + } +} + +void sig_heredoc(int sig) +{ + if (sig == SIGINT) + { + g_error = 130; + ioctl(STDIN_FILENO, TIOCSTI, "\n"); + close_pipe(); + } +} + +void sig_main(t_head *head, int sig_val) +{ + if (SIG_ERR == signal(SIGINT, SIG_IGN)) + ft_exit(head); + if (SIG_ERR == signal(SIGQUIT, SIG_IGN)) + ft_exit(head); + if (sig_val == 0) + { + signal(SIGQUIT, SIG_IGN); + signal(SIGINT, &sig); + } + else if (sig_val == 1) + { + signal(SIGQUIT, &sig_child); + signal(SIGPIPE, &sig_child); + signal(SIGINT, &sig_child); + } + else if (sig_val == 2) + { + signal(SIGQUIT, SIG_IGN); + signal(SIGINT, &sig_heredoc); + } +} diff --git a/includes/builtins.h b/includes/builtins.h new file mode 100644 index 0000000..8bf1c93 --- /dev/null +++ b/includes/builtins.h @@ -0,0 +1,127 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* builtins.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: grebrune +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/26 19:52:23 by grebrune #+# #+# */ +/* Updated: 2024/07/09 01:14:30 by grebrune ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef BUILTINS_H +# define BUILTINS_H + +# include "minishell.h" +# include "errno.h" +# include +# include +# include +# include + +typedef struct s_env t_env; +typedef struct s_redir t_redir; +typedef struct s_cmd t_cmd; +typedef struct s_fnp t_fnp; +typedef struct s_head t_head; + +int ft_cd(t_head *head); +char *cd_relative(t_head *head); +char *cd_find_var(t_head *head, char *name); +char *cd_cat_backslash(char *path, char *dir); +//cd_back +char *cd_tild_trim(t_head *head); +char *cd_back_trim(void); +void cd_chdir_error(t_head *head, char *old_pwd, char *new_pwd); +void cd_not_found(char *name); + +void ft_echo(t_head *head, t_cmd *copy); +void print_tab(t_head *head, char **arg, int i, int n); + +void ft_env(t_head *head); +int checker_env(char **arg); + +void ft_exit(t_head *head); +void exit_write(char *arg); +int ft_strnum(char *str); +int is_num(t_head *head); +//exit_free +void exit_free(t_head *head, int status); +void new_pwd(t_head *head, char *value, char *name); +int replace_value(t_head *head, char *value, char *replace); +char *cat_of_tild(t_head *head, char *str); + +int ft_export(t_head *head); +int export_bis(t_head *head, t_env *c_env, size_t i); +int ft_strcmp_until(char *s1, const char *s2); +char *replace_var_until(char *arg, char *result); +int new_var(t_head *head, char *name); +//export_add +void new_var_bis(t_env *copy, t_head *head, t_env *new); +int export_search_env(t_env *c_env, char *name); +void error_handle(char *str); +int add_var(t_head *head, char *str, t_env *c_env); +//export_checker +int check_name_errors(char *name); +int check_name(t_head *head, char *name, t_env *c_env); +int no_plus(char *name); +//export_utils +int check_equal(char *str); +char *dup_until(char *str); +char *dup_if(char *name); +int ft_strlen_until(char *str); +void free_tab(char **tab); +//built_export_no_arg +char *join_equal(char *name, char *val); +char **env_to_tab(t_env *copy); +void printf_tab(char **tab); +void swap_this_tab(char **tab); +int ex_no_args(t_head *head); + +void ft_pwd(t_head *head); +int get_path(char **str); +int check_dir(t_head *head); +char *value_of_name(t_env *env, char *name); + +void ft_unset(t_head *head); +void rem_env(t_env **env, void *ref, int (*cmp)(char *, const char *)); +//exec_error +void exec_error_exit(char **arg, char **env, char **path); +//exec_main +void exec_shell(char **arg, char *str, char **env); +int find_cmd(t_head *head, t_cmd *copy, t_fnp *fnp, int x); +int exec_shell_malloc(t_head *head, t_cmd *copy, t_fnp *fnp); +int executable(t_head *head); + +//exec_utils +char *find_path(t_head *head); +char *join_with_char(char const *s1, char const *s2, char c); +char **make_env(t_env *env); +void no_path_to_hapiness(t_head *head, char **env, char **tab, t_cmd *copy); +void free_malloc_fnp(t_head *head, int to_free); +//exec_wait +int wait_for_all(pid_t *pid, int x); +size_t envlen(t_env *base); +size_t cmdlen(t_cmd *base); +char **redir_arg(t_cmd *cmd, int type); +char **make_arg(t_cmd *cmd); + +//exec_redir +void fail_malloc(t_head *head, int **fd, size_t i); +int open_the_pipe(int **fd, t_head *head); +int open_files(t_redir *redir, int *err_print); +int open_redir(t_cmd *copy, int fd[2]); + +//exec_redir_utils +int fill_pipe(size_t numb, int **fd, t_head *head); +int redir_with_fd(int fd[2], int **pipe, t_cmd *copy, int x); +void close_pipe(void); +void free_fnp(t_head *head, t_fnp *fnp); +int malloc_fnp(t_head *head); +//heredoc +void clear_heredoc_exec(char **arg, char *str, char **env); +int clear_heredoc(t_head *head); +int heredoc(t_head *head); + +#endif diff --git a/includes/minishell.h b/includes/minishell.h index ccb9e1f..834c680 100644 --- a/includes/minishell.h +++ b/includes/minishell.h @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* minishell.h :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: beroy +#+ +:+ +#+ */ +/* By: grebrune +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/04/11 16:24:43 by beroy #+# #+# */ -/* Updated: 2024/04/11 16:47:32 by beroy ### ########.fr */ +/* Updated: 2024/06/26 20:16:08 by grebrune ### ########.fr */ /* */ /* ************************************************************************** */ @@ -17,6 +17,11 @@ # include # include # include +# include +# include +# include +# include "builtins.h" +# include "parser.h" // COLOR CODES @@ -28,4 +33,49 @@ # define PURPLE "\033[0;35m" # define CYAN "\033[0;36m" +extern int g_error; + +typedef struct s_env +{ + char *name; + char *value; + struct s_env *next; + struct s_env *prev; +} t_env; + +typedef struct s_redir +{ + int type; + int fd; + int quote; + char *arg; + struct s_redir *next; + struct s_redir *prev; +} t_redir; + +typedef struct s_cmd +{ + char *line; + char **arg; + t_redir *redir; + struct s_cmd *next; + struct s_cmd *prev; +} t_cmd; + +typedef struct s_fnp +{ + int *pid; + int **pipe; +} t_fnp; + +typedef struct s_head +{ + t_cmd *cmd; + t_env *env; + t_fnp *fnp; +} t_head; + +//signal +void sig_main(t_head *head, int sig_val); + #endif diff --git a/includes/parser.h b/includes/parser.h new file mode 100644 index 0000000..98e71e4 --- /dev/null +++ b/includes/parser.h @@ -0,0 +1,146 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* parser.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: grebrune +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/18 14:44:03 by beroy #+# #+# */ +/* Updated: 2024/06/28 15:59:26 by grebrune ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef PARSER_H +# define PARSER_H + +typedef struct s_env t_env; +typedef struct s_redir t_redir; +typedef struct s_cmd t_cmd; +typedef struct s_head t_head; + +// backslash.c + +void remove_backslash(char *str); +void format_backslash(t_head *head); + +// expand_var.c + +char *str_dup_var(char *str, int s, int e, char *val); +int replace_var_redir(char *str, t_head *head); +int format_var_redir(t_head *head); +int format_var(t_head *head); + +// expand_var_utils.c + +int find_var(char *str); +int str_cmp_var(char *str, int i, char *value); +char *var_value(char *str, int i, t_env *env); +int find_end_var(char *str, int i); +int replace_var_line(char *str, t_head *head); + +// expand_var_utils.c + +int end_of_var(char c); + +// format_redir.c + +void tab_display(char **tab); +int spaces_to_add(char *str); +void ft_dupwithspace2(char *str, char *dup, int i, int j); +char *ft_dupwithspace(char *str); +int space_redir(t_cmd *cmd); + +// free_func.c + +void ft_free_cmd(t_cmd **cmd); +void ft_free_all(t_head *head); + +// header.c + +char *ft_color(int i); +void ft_header(void); + +// init.c + +t_env *ft_env_new(char *env); +t_env *ft_envlast(t_env *lst); +void ft_envadd_back(t_env **lst, t_env *new); +t_env *env_init(char **env_tab); +t_head *head_init(char **env); + +// init_utils.c + +t_env *ft_env_new_bis(char *name, char *value); +int find_equal(char *str); +t_redir *ft_redir_new(char *line, int start, int end, int type); +t_redir *ft_redirlast(t_redir *lst); +void ft_rediradd_back(t_redir **lst, t_redir *new); + +// init_utils2.c + +t_env *env_if_empty(void); + +// parser.c + +int redir_is_empty(t_redir *redir); +int cmd_is_empty(t_cmd *cmd, int full); +int quote_skip(char *input, int *i, char find); +int check_line(char *input); +t_cmd *split_pipe(char *input); +int ft_parse(char *input, t_head *head); + +// parser_utils.c + +int redir_is_empty(t_redir *redir); +t_cmd *ft_cmd_new(char *input); +t_cmd *ft_cmdlast(t_cmd *lst); +void ft_cmdadd_back(t_cmd **lst, t_cmd *new); +void find_pipe(char *input, int *i); + +// pre_check.c + +int first_pipe(char *str); +int check_pipe(char *input, int *i); +int check_redir(char *input, int *i); +int check_redir_pipe(char *input); + +// redir.c + +int format_redir(t_cmd *cmd); + +// redir_utils.c + +int redir_type(char *line, int i); +int find_redir(char *line); +int find_arg(char *line, int start); +char *dup_without_redir(char *line, int end); +int extract_redir(t_cmd *cmd); + +// split.c + +int ft_countwords(char *input); +int ft_wdlen(char *input, int j); +char **split_ws_quote(char *input); +int split_ws(t_cmd *cmd); + +// trim.c + +int nbr_quote(char *str); +void trim_str_2(char *str, char *trim, int len, int nbr); +char *trim_str(char *str); +int trim_tab(char **tab); +int format(t_head *head); + +// trim_utils.c + +int trim_redir(t_head *head); + +// utils.c + +int str_empty(char *str); +int char_is_ws(char c); +void single_index_up(char *input, int *i); +int char_is_num(char c); +void index_up(char *input, int *i); + +#endif \ No newline at end of file diff --git a/srcs/backslash.c b/srcs/backslash.c new file mode 100644 index 0000000..6cba345 --- /dev/null +++ b/srcs/backslash.c @@ -0,0 +1,54 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* backslash.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: grebrune +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/05/14 16:10:02 by beroy #+# #+# */ +/* Updated: 2024/06/20 17:33:09 by grebrune ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/minishell.h" + +void remove_backslash(char *str) +{ + int i; + int j; + + i = 0; + j = 0; + while (str && str[j]) + { + if (str[j] == '\\' && (str[j + 1] == '$' + || (j != 0 && str[j - 1] == '\\'))) + j++; + str[i] = str[j]; + i++; + j++; + } + str[i] = 0; +} + +void format_backslash(t_head *head) +{ + while (head->cmd) + { + remove_backslash(head->cmd->line); + while (head->cmd->redir) + { + remove_backslash(head->cmd->redir->arg); + if (head->cmd->redir->next == NULL) + break ; + head->cmd->redir = head->cmd->redir->next; + } + while (head->cmd->redir && head->cmd->redir->prev) + head->cmd->redir = head->cmd->redir->prev; + if (head->cmd->next == NULL) + break ; + head->cmd = head->cmd->next; + } + while (head->cmd->prev) + head->cmd = head->cmd->prev; +} diff --git a/srcs/expand_var.c b/srcs/expand_var.c new file mode 100644 index 0000000..615bc12 --- /dev/null +++ b/srcs/expand_var.c @@ -0,0 +1,90 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* expand_var.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: beroy +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/19 14:03:41 by beroy #+# #+# */ +/* Updated: 2024/06/27 13:08:22 by beroy ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/minishell.h" + +char *str_dup_var(char *str, int s, int e, char *val) +{ + int i; + int j; + char *dup; + + i = 0; + j = 0; + dup = ft_calloc(ft_strlen(str) - e + s + ft_strlen(val) + 1, sizeof(char)); + if (dup == NULL) + return (NULL); + while (i < s) + dup[j++] = str[i++]; + i = 0; + while (val[i]) + dup[j++] = val[i++]; + while (str[e]) + dup[j++] = str[e++]; + return (ft_free(str), ft_free(val), dup); +} + +int replace_var_redir(char *str, t_head *head) +{ + int start; + int end; + char *value; + + start = find_var(str); + end = find_end_var(str, start); + value = var_value(str, start + 1, head->env); + if (value == NULL) + return (1); + head->cmd->redir->arg = str_dup_var(str, start, end, value); + if (str == NULL) + return (1); + return (0); +} + +int format_var_redir(t_head *head) +{ + while (head->cmd->redir) + { + while (head->cmd->redir->type != 4 + && find_var(head->cmd->redir->arg) != -1) + { + if (replace_var_redir(head->cmd->redir->arg, head) == 1) + return (1); + } + if (head->cmd->redir->next == NULL) + break ; + head->cmd->redir = head->cmd->redir->next; + } + while (head->cmd->redir && head->cmd->redir->prev) + head->cmd->redir = head->cmd->redir->prev; + return (0); +} + +int format_var(t_head *head) +{ + while (head->cmd) + { + while (find_var(head->cmd->line) != -1) + { + if (replace_var_line(head->cmd->line, head) == 1) + return (1); + } + if (format_var_redir(head) == 1) + return (1); + if (head->cmd->next == NULL) + break ; + head->cmd = head->cmd->next; + } + while (head->cmd->prev) + head->cmd = head->cmd->prev; + return (0); +} diff --git a/srcs/expand_var_utils.c b/srcs/expand_var_utils.c new file mode 100644 index 0000000..e71cac5 --- /dev/null +++ b/srcs/expand_var_utils.c @@ -0,0 +1,111 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* expand_var_utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: grebrune +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/05/14 13:55:23 by beroy #+# #+# */ +/* Updated: 2024/07/08 13:34:22 by grebrune ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/minishell.h" + +int find_var(char *str) +{ + int i; + + i = 0; + while (str[i]) + { + if (str[i] == '$') + { + if (i == 0) + return (i); + if (i > 0 && str[i - 1] != '\\') + return (i); + if (i > 1 && str[i - 1] == '\\' && str[i - 2] == '\\') + return (i); + } + single_index_up(str, &i); + } + return (-1); +} + +int str_cmp_var(char *str, int i, char *value) +{ + int j; + + j = 0; + while (str[i] && value[j] && str[i] == value[j]) + { + i++; + j++; + } + if (end_of_var(str[i]) == 1 && value[j] == 0) + return (1); + return (0); +} + +char *var_value(char *str, int i, t_env *env) +{ + char *value; + + value = NULL; + while (env && value == NULL) + { + if (str_cmp_var(str, i, env->name) == 1) + { + value = ft_strdup(env->value); + if (value == NULL) + return (NULL); + } + if (env->next == NULL) + break ; + env = env->next; + } + if (value == NULL && str[i] == '?') + value = ft_itoa(g_error); + if (value == NULL) + value = ft_strdup(""); + while (env && env->prev) + env = env->prev; + return (value); +} + +int find_end_var(char *str, int i) +{ + int j; + + i++; + j = i; + while (str && str[i]) + { + if (str[i] == '?') + return (i + 1); + if (end_of_var(str[i]) == 1) + break ; + if (j == i && char_is_num(str[i]) == 1) + return (i + 1); + single_index_up(str, &i); + } + return (i); +} + +int replace_var_line(char *str, t_head *head) +{ + int start; + int end; + char *value; + + start = find_var(str); + end = find_end_var(str, start); + value = var_value(str, start + 1, head->env); + if (value == NULL) + return (1); + head->cmd->line = str_dup_var(str, start, end, value); + if (str == NULL) + return (1); + return (0); +} diff --git a/srcs/expand_var_utils2.c b/srcs/expand_var_utils2.c new file mode 100644 index 0000000..07605a0 --- /dev/null +++ b/srcs/expand_var_utils2.c @@ -0,0 +1,26 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* expand_var_utils2.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: beroy +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/28 18:32:58 by beroy #+# #+# */ +/* Updated: 2024/06/28 18:37:44 by beroy ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/minishell.h" + +int end_of_var(char c) +{ + if (char_is_num(c) == 1) + return (0); + if (c == '_') + return (0); + if (c >= 65 && c <= 90) + return (0); + if (c >= 97 && c <= 122) + return (0); + return (1); +} diff --git a/srcs/format_redir.c b/srcs/format_redir.c new file mode 100644 index 0000000..9245bdb --- /dev/null +++ b/srcs/format_redir.c @@ -0,0 +1,98 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* parser_utils_3.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: beroy +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/22 17:36:26 by beroy #+# #+# */ +/* Updated: 2024/06/17 18:11:26 by beroy ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/minishell.h" + +int spaces_to_add(char *str) +{ + int i; + int spaces; + + i = 0; + spaces = 0; + while (str[i]) + { + if (str[i] == '<') + { + if (str[i + 1] == '<') + i++; + spaces += 2; + } + else if (str[i] == '>') + { + if (str[i + 1] == '>') + i++; + spaces += 2; + } + index_up(str, &i); + } + return (spaces); +} + +void ft_dupwithspace2(char *str, char *dup, int i, int j) +{ + char quote; + + quote = 0; + while (str[i]) + { + if (quote == 0 && (str[i] == 34 || str[i] == 39)) + quote = str[i]; + else if (str[i] == quote) + quote = 0; + if (quote == 0 && (str[i] == '<' || str[i] == '>')) + { + dup[j++] = ' '; + dup[j++] = str[i]; + if (str[i + 1] == str[i]) + { + dup[j++] = str[i]; + i++; + } + dup[j++] = ' '; + } + else + dup[j++] = str[i]; + i++; + } +} + +char *ft_dupwithspace(char *str) +{ + int i; + int j; + char *dup; + + i = 0; + j = 0; + dup = ft_calloc(ft_strlen(str) + spaces_to_add(str) + 1, sizeof(char)); + if (dup == NULL) + return (NULL); + ft_dupwithspace2(str, dup, i, j); + return (ft_free(str), dup); +} + +int space_redir(t_cmd *cmd) +{ + while (cmd) + { + cmd->line = ft_dupwithspace(cmd->line); + if (cmd->line == NULL) + return (1); + if (cmd->next == NULL) + break ; + cmd = cmd->next; + } + while (cmd->prev) + cmd = cmd->prev; + return (0); +} diff --git a/srcs/free_func.c b/srcs/free_func.c new file mode 100644 index 0000000..bed64a1 --- /dev/null +++ b/srcs/free_func.c @@ -0,0 +1,56 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* free_func.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: grebrune +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/20 17:57:26 by beroy #+# #+# */ +/* Updated: 2024/06/27 17:40:52 by grebrune ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/minishell.h" + +void ft_free_cmd(t_cmd **cmd) +{ + t_redir *tmp_redir; + t_cmd *tmp_cmd; + + while ((*cmd)) + { + tmp_cmd = (*cmd)->next; + if ((*cmd)->arg) + ft_splitdestroy((*cmd)->arg); + if ((*cmd)->line) + ft_free((*cmd)->line); + while ((*cmd)->redir != NULL) + { + tmp_redir = (*cmd)->redir->next; + ft_free((*cmd)->redir->arg); + ft_free((*cmd)->redir); + (*cmd)->redir = tmp_redir; + } + if ((*cmd) != NULL) + ft_free(*cmd); + (*cmd) = tmp_cmd; + } +} + +void ft_free_all(t_head *head) +{ + t_env *tmp; + + if (head->cmd != NULL) + ft_free_cmd(&(head->cmd)); + while (head->env != NULL) + { + tmp = head->env->next; + ft_free(head->env->name); + ft_free(head->env->value); + ft_free(head->env); + head->env = tmp; + } + if (head != NULL) + ft_free(head); +} diff --git a/srcs/header.c b/srcs/header.c new file mode 100644 index 0000000..c0dbece --- /dev/null +++ b/srcs/header.c @@ -0,0 +1,52 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* header.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: beroy +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/20 17:55:35 by beroy #+# #+# */ +/* Updated: 2024/06/20 17:55:35 by beroy ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/minishell.h" + +char *ft_color(int i) +{ + if (i % 6 == 0) + return (ft_strdup(YELLOW)); + if (i % 6 == 1) + return (ft_strdup(GREEN)); + if (i % 6 == 2) + return (ft_strdup(CYAN)); + if (i % 6 == 3) + return (ft_strdup(BLUE)); + if (i % 6 == 4) + return (ft_strdup(PURPLE)); + else + return (ft_strdup(RED)); +} + +void ft_header(void) +{ + char *str; + char *color; + int fd; + int i; + + fd = open("data/header.txt", O_RDONLY); + str = get_next_line(fd); + i = 0; + while (str) + { + color = ft_color(i); + printf("%s%s", color, str); + ft_free (str); + ft_free (color); + str = get_next_line(fd); + i++; + } + printf("\033[0m\n"); + close (fd); +} diff --git a/srcs/init.c b/srcs/init.c new file mode 100644 index 0000000..54f98dc --- /dev/null +++ b/srcs/init.c @@ -0,0 +1,94 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* init.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: grebrune +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/18 17:14:37 by beroy #+# #+# */ +/* Updated: 2024/07/08 21:45:22 by grebrune ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/minishell.h" + +t_env *ft_env_new(char *env) +{ + t_env *s_new; + int equal; + + equal = find_equal(env) + 1; + s_new = ft_calloc(1, sizeof(t_env)); + if (s_new == NULL) + return (s_new); + s_new->name = ft_substr(env, 0, equal - 1); + if (s_new->name == NULL) + return (free(s_new), NULL); + s_new->value = ft_substr(env, equal, ft_strlen(env) - equal); + if (s_new->value == NULL) + return (ft_free(s_new->name), ft_free(s_new), NULL); + s_new->next = NULL; + s_new->prev = NULL; + return (s_new); +} + +t_env *ft_envlast(t_env *lst) +{ + if (!lst) + return (NULL); + while (lst->next != NULL) + lst = lst->next; + return (lst); +} + +void ft_envadd_back(t_env **lst, t_env *new) +{ + t_env *last; + + if (lst) + { + if (*lst == NULL) + *lst = new; + else + { + last = ft_envlast(*lst); + last->next = new; + new->prev = last; + } + } +} + +t_env *env_init(char **env_tab) +{ + int i; + t_env *new; + t_env *env; + + if (env_tab && !env_tab[0]) + return (env_if_empty()); + i = 0; + env = NULL; + while (env_tab[i]) + { + new = ft_env_new(env_tab[i]); + if (new == NULL) + return (NULL); + ft_envadd_back(&env, new); + i++; + } + return (env); +} + +t_head *head_init(char **env) +{ + t_head *head; + + head = ft_calloc(1, sizeof(t_head)); + if (head == NULL) + return (printf("Malloc failed!\n"), NULL); + head->env = env_init(env); + if (head->env == NULL) + return (printf("Malloc failed!\n"), free(head), NULL); + head->cmd = NULL; + return (head); +} diff --git a/srcs/init_utils.c b/srcs/init_utils.c new file mode 100644 index 0000000..30ce646 --- /dev/null +++ b/srcs/init_utils.c @@ -0,0 +1,85 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* init_utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: grebrune +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/29 16:59:12 by beroy #+# #+# */ +/* Updated: 2024/06/26 19:54:15 by grebrune ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/minishell.h" + +t_env *ft_env_new_bis(char *name, char *value) +{ + t_env *s_new; + + s_new = ft_calloc(1, sizeof(t_env)); + if (s_new == NULL) + return (s_new); + s_new->name = ft_strdup(name); + if (s_new->name == NULL) + return (free(s_new), NULL); + s_new->value = ft_strdup(value); + if (s_new->value == NULL) + return (ft_free(s_new->name), ft_free(s_new), NULL); + s_new->next = NULL; + s_new->prev = NULL; + return (s_new); +} + +int find_equal(char *str) +{ + int i; + + i = 0; + while (str[i] && str[i] != '=') + i++; + return (i); +} + +t_redir *ft_redir_new(char *line, int start, int end, int type) +{ + t_redir *s_new; + + s_new = ft_calloc(1, sizeof(t_redir)); + if (s_new == NULL) + return (s_new); + s_new->type = type; + s_new->arg = ft_substr(line, start, end - start + 1); + if (s_new->arg == NULL) + return (ft_free(s_new), NULL); + s_new->next = NULL; + s_new->prev = NULL; + s_new->fd = -1; + s_new->quote = 0; + return (s_new); +} + +t_redir *ft_redirlast(t_redir *lst) +{ + if (!lst) + return (NULL); + while (lst->next != NULL) + lst = lst->next; + return (lst); +} + +void ft_rediradd_back(t_redir **lst, t_redir *new) +{ + t_redir *last; + + if (lst) + { + if (*lst == NULL) + *lst = new; + else + { + last = ft_redirlast(*lst); + last->next = new; + new->prev = last; + } + } +} diff --git a/srcs/init_utils2.c b/srcs/init_utils2.c new file mode 100644 index 0000000..ae53df6 --- /dev/null +++ b/srcs/init_utils2.c @@ -0,0 +1,34 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* init_utils2.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: grebrune +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/26 20:10:22 by grebrune #+# #+# */ +/* Updated: 2024/07/08 21:58:20 by grebrune ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/minishell.h" + +t_env *env_if_empty(void) +{ + t_env *new; + t_env *env; + char *str; + + env = NULL; + str = NULL; + if (get_path(&str) == 2) + return (NULL); + new = ft_env_new_bis("PWD", str); + if (new == NULL) + return (NULL); + ft_envadd_back(&env, new); + new = ft_env_new_bis("SHLVL", "1"); + if (new == NULL) + return (NULL); + ft_envadd_back(&env, new); + return (env); +} diff --git a/srcs/main.c b/srcs/main.c index e4273c0..91ed932 100644 --- a/srcs/main.c +++ b/srcs/main.c @@ -3,58 +3,113 @@ /* ::: :::::::: */ /* main.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: beroy +#+ +:+ +#+ */ +/* By: grebrune +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/04/11 16:11:53 by beroy #+# #+# */ -/* Updated: 2024/04/11 18:40:37 by beroy ### ########.fr */ +/* Updated: 2024/07/08 21:44:00 by grebrune ### ########.fr */ /* */ /* ************************************************************************** */ #include "../includes/minishell.h" -char *ft_color(int i) + +int g_error = 0; + +int single_exec(t_head *head, char *input) +{ + sig_main(head, 0); + if (input == NULL || str_empty(input) == 1) + return (0); + if (ft_parse(input, head) == 0) + { + heredoc(head); + if (cmd_is_empty(head->cmd, 0) == 0) + executable(head); + } + return (0); +} + +int open_on_err(t_cmd *cmd) +{ + t_cmd *c_cmd; + t_redir *red; + + c_cmd = cmd; + while (c_cmd) + { + red = c_cmd->redir; + while (red) + { + if (red->type == 1) + red->fd = open(red->arg, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (red->type == 2) + red->fd = open(red->arg, O_WRONLY | O_CREAT | O_APPEND, 0644); + if ((red->type == 2 || red->type == 1) && red->fd == -1) + return (perror(red->arg), 2); + red = red->next; + } + c_cmd = c_cmd->next; + } + return (0); +} + +void here_exec(t_head *head, char *input) { - if (i % 6 == 0) - return (YELLOW); - if (i % 6 == 1) - return (GREEN); - if (i % 6 == 2) - return (CYAN); - if (i % 6 == 3) - return (BLUE); - if (i % 6 == 4) - return (PURPLE); - else - return (RED); + if (ft_parse(input, head) == 0) + { + if (heredoc(head)) + { + if (cmd_is_empty(head->cmd, 0) == 0) + executable(head); + else + { + open_on_err(head->cmd); + close_pipe(); + } + } + } + if (head->cmd != NULL) + ft_free_cmd(&(head->cmd)); + free(input); } -void ft_header(void) +void main_loop(t_head *head) { - char *str; - char *color; - int fd; - int i; - - fd = open("data/header.txt", O_RDONLY); - str = get_next_line(fd); - i = 0; - while (str) + char *input; + + while (42) { - color = ft_color(i); - printf("%s%s", color, str); - str = get_next_line(fd); - i++; + sig_main(head, 0); + input = readline("> "); + if (input == NULL) + { + free(input); + break ; + } + add_history(input); + sig_main(head, 3); + if (str_empty(input) == 1) + { + free(input); + continue ; + } + here_exec(head, input); } - printf("\033[0m\n"); + write(1, "exit\n", 5); } -int main(void) +int main(int ac, char **av, char **env) { - char input[1025]; - size_t rd; + t_head *head; + (void)ac; + (void)av; ft_header(); - write(1, "> ", 2); - rd = read(1, input, 1024); - input[rd] = 0; - printf("%s", input); + head = head_init(env); + if (head == NULL) + return (0); + if (ac == 1) + main_loop(head); + if (ac == 2) + single_exec(head, av[1]); + return (ft_free_all(head), g_error); } diff --git a/srcs/parser.c b/srcs/parser.c new file mode 100644 index 0000000..da470e1 --- /dev/null +++ b/srcs/parser.c @@ -0,0 +1,128 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* parser.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: grebrune +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/17 13:19:51 by beroy #+# #+# */ +/* Updated: 2024/07/08 15:09:18 by grebrune ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/minishell.h" + +int cmd_is_empty(t_cmd *cmd, int full) +{ + int i; + int ret; + + ret = 1; + while (cmd) + { + i = 0; + while (cmd->arg[i]) + { + if (str_empty(cmd->arg[i]) == 0) + ret = 0; + i++; + } + if (full == 1 && redir_is_empty(cmd->redir) == 0) + ret = 0; + if (cmd->next == NULL) + break ; + cmd = cmd->next; + } + while (cmd->prev) + cmd = cmd->prev; + return (ret); +} + +int quote_skip(char *input, int *i, char find) +{ + *i += 1; + while (input[*i] != 0 && input[*i] != find) + *i += 1; + if (input[*i] == 0) + return (1); + return (0); +} + +int check_line(char *input) +{ + int i; + + i = 0; + if (first_pipe(input) == 1) + return (1); + if (str_empty(input) == 1) + return (1); + if (check_redir_pipe(input) == 1) + return (1); + while (input[i]) + { + if (input[i] == '|') + { + if (input[i + 1] == '|') + return (1); + } + else if (input[i] == 34 || input[i] == 39) + { + if (quote_skip(input, &i, input[i]) == 1) + return (1); + } + i++; + } + return (0); +} + +t_cmd *split_pipe(char *input) +{ + t_cmd *cmd; + t_cmd *new; + char *extract; + int offset; + int i; + + offset = 0; + i = 0; + cmd = NULL; + while (input[i]) + { + find_pipe(input, &i); + extract = ft_substr(input, offset, i - offset); + if (extract == NULL) + return (ft_free_cmd(&cmd), NULL); + new = ft_cmd_new(extract); + if (new == NULL) + return (ft_free_cmd(&cmd), NULL); + ft_cmdadd_back(&cmd, new); + if (input[i] != 0) + i++; + offset = i; + } + return (cmd); +} + +int ft_parse(char *input, t_head *head) +{ + if (check_line(input) == 1) + return (write(2, "bash: syntax error\n", 19), 1); + head->cmd = split_pipe(input); + if (head->cmd == NULL) + return (1); + if (space_redir(head->cmd) == 1) + return (1); + if (format_redir(head->cmd) == 1) + return (1); + if (format_var(head) == 1) + return (1); + format_backslash(head); + if (split_ws(head->cmd) == 1) + return (1); + if (format(head) == 1) + return (1); + if (cmd_is_empty(head->cmd, 1) == 1) + return (write(2, "bash: syntax error\n", 19), 1); + return (0); +} diff --git a/srcs/parser_utils.c b/srcs/parser_utils.c new file mode 100644 index 0000000..c67222e --- /dev/null +++ b/srcs/parser_utils.c @@ -0,0 +1,84 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* parser_utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: grebrune +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/22 13:21:52 by beroy #+# #+# */ +/* Updated: 2024/06/28 15:59:26 by grebrune ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/minishell.h" + +int redir_is_empty(t_redir *redir) +{ + int ret; + + ret = 1; + if (!redir) + return (ret); + while (redir) + { + if (str_empty(redir->arg) == 0) + ret = 0; + if (redir->next == NULL) + break ; + redir = redir->next; + } + while (redir->prev) + redir = redir->prev; + return (ret); +} + +t_cmd *ft_cmd_new(char *input) +{ + t_cmd *s_new; + + s_new = ft_calloc(1, sizeof(t_cmd)); + if (s_new == NULL) + return (s_new); + s_new->line = input; + s_new->arg = NULL; + s_new->redir = NULL; + s_new->next = NULL; + s_new->prev = NULL; + return (s_new); +} + +t_cmd *ft_cmdlast(t_cmd *lst) +{ + if (!lst) + return (NULL); + while (lst->next != NULL) + lst = lst->next; + return (lst); +} + +void ft_cmdadd_back(t_cmd **lst, t_cmd *new) +{ + t_cmd *last; + + if (lst) + { + if (*lst == NULL) + *lst = new; + else + { + last = ft_cmdlast(*lst); + last->next = new; + new->prev = last; + } + } +} + +void find_pipe(char *input, int *i) +{ + while (input[*i]) + { + if (input[*i] == '|' || input [*i] == 0) + return ; + index_up(input, i); + } +} diff --git a/srcs/pre_check.c b/srcs/pre_check.c new file mode 100644 index 0000000..e2d4439 --- /dev/null +++ b/srcs/pre_check.c @@ -0,0 +1,77 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* pre_check.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: grebrune +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/03 14:45:58 by beroy #+# #+# */ +/* Updated: 2024/06/28 16:00:01 by grebrune ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/minishell.h" + +int first_pipe(char *str) +{ + int i; + + i = 0; + while (str && str[i] && str[i] != '|') + { + if (char_is_ws(str[i]) == 0) + return (0); + i++; + } + return (1); +} + +int check_pipe(char *input, int *i) +{ + int nbr; + + nbr = 0; + if (*i != 0 && input[*i - 1] == input[*i]) + nbr++; + if (input[*i] == input[*i + 1]) + nbr++; + if (nbr >= 2) + return (1); + return (0); +} + +int check_redir(char *input, int *i) +{ + int nbr; + + nbr = 0; + if (input[*i] == '<' && input[*i + 1] == '>') + return (1); + if (input[*i] == '>' && input[*i + 1] == '<') + return (1); + if (*i != 0 && input[*i - 1] == input[*i]) + nbr++; + if (input[*i] == input[*i + 1]) + nbr++; + if (nbr >= 2) + return (1); + return (0); +} + +int check_redir_pipe(char *input) +{ + int i; + + i = 0; + while (input && input[i]) + { + if (input[i] == '|') + if (check_pipe(input, &i) == 1) + return (1); + if (input[i] == '<' || input[i] == '>') + if (check_redir(input, &i) == 1) + return (1); + index_up(input, &i); + } + return (0); +} diff --git a/srcs/redir.c b/srcs/redir.c new file mode 100644 index 0000000..40566f5 --- /dev/null +++ b/srcs/redir.c @@ -0,0 +1,31 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* redir.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: beroy +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/19 14:02:57 by beroy #+# #+# */ +/* Updated: 2024/06/19 14:06:05 by beroy ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/minishell.h" + +int format_redir(t_cmd *cmd) +{ + while (cmd) + { + while (find_redir(cmd->line) == 1) + { + if (extract_redir(cmd) == 1) + return (1); + } + if (cmd->next == NULL) + break ; + cmd = cmd->next; + } + while (cmd->prev) + cmd = cmd->prev; + return (0); +} diff --git a/srcs/redir_utils.c b/srcs/redir_utils.c new file mode 100644 index 0000000..27109cf --- /dev/null +++ b/srcs/redir_utils.c @@ -0,0 +1,111 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* redir_utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: grebrune +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/05/13 15:00:16 by beroy #+# #+# */ +/* Updated: 2024/06/26 20:22:45 by grebrune ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/minishell.h" + +int redir_type(char *line, int i) +{ + if (line[i] == '>') + { + if (line[i + 1] == '>') + return (2); + else + return (1); + } + else if (line[i] == '<') + { + if (line[i + 1] == '<') + return (4); + else + return (3); + } + else + return (0); +} + +int find_redir(char *line) +{ + int i; + + i = 0; + while (line[i]) + { + if (redir_type(line, i) != 0) + return (1); + index_up(line, &i); + } + return (0); +} + +int find_arg(char *line, int start) +{ + while (line[start] && char_is_ws(line[start]) == 1) + index_up(line, &start); + while (line[start] && char_is_ws(line[start]) == 0) + index_up(line, &start); + return (start - 1); +} + +char *dup_without_redir(char *line, int end) +{ + int i; + int j; + char *dup; + int start; + + i = 0; + j = 0; + start = 0; + while (redir_type(line, start) == 0) + index_up(line, &start); + dup = ft_calloc(ft_strlen(line) - end + start + 1, sizeof(char)); + if (dup == NULL) + return (ft_free(line), NULL); + while (line[i]) + { + if (i == start) + i = end + 1; + dup[j] = line[i]; + if (line[i] != 0) + i++; + j++; + } + return (ft_free(line), dup); +} + +int extract_redir(t_cmd *cmd) +{ + int start; + int end; + int type; + t_redir *new; + + start = 0; + while (redir_type(cmd->line, start) == 0) + index_up(cmd->line, &start); + type = redir_type(cmd->line, start); + if (type % 2 == 0) + start += 2; + else + start++; + while (char_is_ws(cmd->line[start]) == 1) + start++; + end = find_arg(cmd->line, start); + new = ft_redir_new(cmd->line, start, end, type); + if (new == NULL) + return (1); + ft_rediradd_back(&cmd->redir, new); + cmd->line = dup_without_redir(cmd->line, end); + if (cmd->line == NULL) + return (1); + return (0); +} diff --git a/srcs/split.c b/srcs/split.c new file mode 100644 index 0000000..982ce1c --- /dev/null +++ b/srcs/split.c @@ -0,0 +1,108 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* split.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: grebrune +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/22 16:18:25 by beroy #+# #+# */ +/* Updated: 2024/06/27 17:38:42 by grebrune ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/minishell.h" + +int ft_countwords(char *input) +{ + int i; + int wds; + + wds = 0; + i = 0; + if (char_is_ws(input[i]) == 0 && input [i]) + wds++; + index_up(input, &i); + while (input[i]) + { + if (char_is_ws(input[i]) == 0 && char_is_ws(input[i - 1]) == 1) + wds++; + index_up(input, &i); + } + return (wds); +} + +int ft_wdlen(char *input, int j) +{ + int i; + + i = j; + while (char_is_ws(input[i]) == 0 && input[i]) + index_up(input, &i); + return (i); +} + +static char *ft_superdup(char *s, int *j) +{ + char *str; + int len; + int i; + + len = ft_wdlen(s, *j); + str = ft_calloc(len - *j + 1, sizeof(char)); + if (str == NULL) + return (str); + i = 0; + while (*j < len) + { + str[i] = s[*j]; + *j += 1; + i++; + } + str[i] = 0; + return (str); +} + +char **split_ws_quote(char *input) +{ + int i; + int j; + int words; + char **split; + + i = 0; + j = 0; + words = ft_countwords(input); + split = ft_calloc(words + 1, sizeof(char *)); + if (split == NULL) + return (NULL); + while (i < words) + { + if (char_is_ws(input[j]) == 0) + { + split[i] = ft_superdup(input, &j); + if (split[i] == NULL) + return (ft_splitdestroy(split)); + i++; + } + else + index_up(input, &j); + } + return (split); +} + +int split_ws(t_cmd *cmd) +{ + while (cmd->next) + { + cmd->arg = split_ws_quote(cmd->line); + if (cmd->arg == NULL) + return (1); + cmd = cmd->next; + } + cmd->arg = split_ws_quote(cmd->line); + if (cmd->arg == NULL) + return (1); + while (cmd->prev) + cmd = cmd->prev; + return (0); +} diff --git a/srcs/trim.c b/srcs/trim.c new file mode 100644 index 0000000..940276b --- /dev/null +++ b/srcs/trim.c @@ -0,0 +1,114 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* trim.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: beroy +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/04/25 15:00:48 by beroy #+# #+# */ +/* Updated: 2024/06/19 16:59:47 by beroy ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/minishell.h" + +int nbr_quote(char *str) +{ + int i; + int nbr; + char find; + + i = 0; + nbr = 0; + while (str && str[i]) + { + if (str[i] == 34 || str[i] == 39) + { + find = str[i]; + if (quote_skip(str, &i, find) == 1) + nbr++; + else + nbr += 2; + } + i++; + } + return (nbr); +} + +void trim_str_2(char *str, char *trim, int len, int nbr) +{ + int i; + int j; + int trigger; + char find; + + i = 0; + j = 0; + trigger = 0; + while (i < len - nbr) + { + if (trigger == 0 && (str[j] == 34 || str[j] == 39)) + { + find = str[j]; + trigger = 1; + j++; + } + else if (trigger == 1 && str[j] == find) + { + trigger = 0; + j++; + } + else + trim[i++] = str[j++]; + } +} + +char *trim_str(char *str) +{ + char *trim; + int len; + int nbr; + + nbr = nbr_quote(str); + if (nbr <= 1) + return (str); + len = (int)ft_strlen(str); + trim = ft_calloc(len - nbr + 1, sizeof(char)); + if (trim == NULL) + return (NULL); + trim_str_2(str, trim, len, nbr); + ft_free(str); + return (trim); +} + +int trim_tab(char **tab) +{ + int i; + + i = 0; + while (tab[i]) + { + tab[i] = trim_str(tab[i]); + if (tab[i] == NULL) + return (1); + i++; + } + return (0); +} + +int format(t_head *head) +{ + while (head->cmd) + { + if (trim_tab(head->cmd->arg) == 1) + return (1); + if (head->cmd->redir && trim_redir(head) == 1) + return (1); + if (head->cmd->next == NULL) + break ; + head->cmd = head->cmd->next; + } + while (head->cmd->prev) + head->cmd = head->cmd->prev; + return (0); +} diff --git a/srcs/trim_utils.c b/srcs/trim_utils.c new file mode 100644 index 0000000..4b17bb9 --- /dev/null +++ b/srcs/trim_utils.c @@ -0,0 +1,31 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* trim_utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: beroy +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/21 13:54:15 by beroy #+# #+# */ +/* Updated: 2024/06/21 14:20:52 by beroy ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/minishell.h" + +int trim_redir(t_head *head) +{ + while (head->cmd->redir) + { + if (nbr_quote(head->cmd->redir->arg) > 1) + head->cmd->redir->quote = 1; + head->cmd->redir->arg = trim_str(head->cmd->redir->arg); + if (head->cmd->redir->arg == NULL) + return (1); + if (head->cmd->redir->next == NULL) + break ; + head->cmd->redir = head->cmd->redir->next; + } + while (head->cmd->redir->prev) + head->cmd->redir = head->cmd->redir->prev; + return (0); +} diff --git a/srcs/utils.c b/srcs/utils.c new file mode 100644 index 0000000..c874556 --- /dev/null +++ b/srcs/utils.c @@ -0,0 +1,59 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: grebrune +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/19 14:16:23 by beroy #+# #+# */ +/* Updated: 2024/07/08 14:53:09 by grebrune ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../includes/minishell.h" + +int str_empty(char *str) +{ + int i; + + i = 0; + while (str[i]) + { + if (char_is_ws(str[i]) == 0) + return (0); + i++; + } + return (1); +} + +int char_is_ws(char c) +{ + if ((c > 7 && c < 13) || c == ' ') + return (1); + return (0); +} + +void single_index_up(char *input, int *i) +{ + if (input[*i] == 39) + quote_skip(input, i, 39); + if (input[*i] != 0) + *i += 1; +} + +int char_is_num(char c) +{ + if (c >= 48 && c <= 57) + return (1); + return (0); +} + +void index_up(char *input, int *i) +{ + if (input[*i] == 34) + quote_skip(input, i, 34); + else if (input[*i] == 39) + quote_skip(input, i, 39); + if (input[*i] != 0) + *i += 1; +} diff --git a/super_libft/Makefile b/super_libft/Makefile index 2c4fe01..6cdfef5 100644 --- a/super_libft/Makefile +++ b/super_libft/Makefile @@ -25,8 +25,10 @@ SRCS = ft_atoi.c \ ft_strlcpy.c \ ft_strlen.c \ ft_strmapi.c \ + ft_strcmp.c \ ft_strncmp.c \ ft_strnstr.c \ + ft_strstr.c \ ft_strrchr.c \ ft_strtrim.c \ ft_substr.c \ @@ -44,7 +46,8 @@ SRCS = ft_atoi.c \ get_next_line.c \ get_next_line_utils.c \ ft_printf.c \ - ft_printf_utils.c + ft_printf_utils.c \ + ft_free.c SRCS_D := srcs/ diff --git a/super_libft/libft.h b/super_libft/libft.h index 3810575..8a5d0d7 100644 --- a/super_libft/libft.h +++ b/super_libft/libft.h @@ -33,12 +33,14 @@ typedef struct s_list struct s_list *next; } t_list; +void ft_free(void *ptr); void ft_bzero(void *s, size_t n); void ft_striteri(char *s, void (*f)(unsigned int, char*)); void ft_putchar_fd(char c, int fd); void ft_putstr_fd(char *str, int fd); void ft_putendl_fd(char *s, int fd); void ft_putnbr_fd(int n, int fd); +void *ft_splitdestroy(char **split); void *ft_memchr(const void *s, int c, size_t n); void *ft_memcpy(void *dest, const void *src, size_t n); @@ -48,6 +50,7 @@ void *ft_calloc(size_t nmemb, size_t size); int ft_memcmp(const void *s1, const void *s2, size_t n); int ft_strncmp(char *s1, const char *s2, size_t n); +int ft_strcmp(char *s1, const char *s2); int ft_isalnum(int c); int ft_isalpha(int c); int ft_isascii(int c); @@ -70,6 +73,7 @@ char *ft_strtrim(char const *s1, char const *set); char *ft_itoa(int n); char *ft_strmapi(char const *s, char (*f)(unsigned int, char)); char *ft_strnstr(const char *big, const char *little, size_t len); +char *ft_strstr(char *str, char *to_find); char **ft_split(char const *s, char c); @@ -96,6 +100,7 @@ void ft_buffclean(char *str); // Prinft int ft_printf(const char *str, ...); +int ft_printf_fd(int fd, const char *str, ...); ssize_t ft_putchar(int c); ssize_t ft_putstr(char *str); void ft_putnbr_base(ssize_t nbr, char *str, ssize_t *length); diff --git a/super_libft/srcs/ft_atoi.c b/super_libft/srcs/ft_atoi.c index 14c435f..6714275 100644 --- a/super_libft/srcs/ft_atoi.c +++ b/super_libft/srcs/ft_atoi.c @@ -14,9 +14,9 @@ int ft_atoi(const char *nptr) { - int i; - int res; - int sign; + size_t i; + int res; + int sign; i = 0; res = 0; diff --git a/super_libft/srcs/ft_free.c b/super_libft/srcs/ft_free.c new file mode 100644 index 0000000..ad15bb3 --- /dev/null +++ b/super_libft/srcs/ft_free.c @@ -0,0 +1,21 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_free.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: grebrune +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/26 17:41:19 by grebrune #+# #+# */ +/* Updated: 2024/06/26 17:44:02 by grebrune ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../libft.h" + +void ft_free(void *ptr) +{ + if (!ptr) + return ; + free(ptr); + ptr = NULL; +} diff --git a/super_libft/srcs/ft_printf.c b/super_libft/srcs/ft_printf.c index dbf05e9..0ee48c4 100644 --- a/super_libft/srcs/ft_printf.c +++ b/super_libft/srcs/ft_printf.c @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* ft_printf.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: beroy +#+ +:+ +#+ */ +/* By: grebrune +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/11/20 19:03:15 by beroy #+# #+# */ -/* Updated: 2024/01/17 16:17:27 by beroy ### ########.fr */ +/* Updated: 2024/06/12 15:51:10 by grebrune ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/super_libft/srcs/ft_split.c b/super_libft/srcs/ft_split.c index 95127d5..1e34fb1 100644 --- a/super_libft/srcs/ft_split.c +++ b/super_libft/srcs/ft_split.c @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* ft_split.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: beroy +#+ +:+ +#+ */ +/* By: grebrune +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/11/08 12:27:55 by beroy #+# #+# */ -/* Updated: 2023/11/14 13:50:14 by beroy ### ########.fr */ +/* Updated: 2024/06/27 17:38:42 by grebrune ### ########.fr */ /* */ /* ************************************************************************** */ @@ -48,7 +48,7 @@ static char *ft_superdup(char const *s, char c, size_t *j) size_t i; len = ft_wdlen(s, c, *j); - str = malloc(sizeof(char) * (len - *j + 1)); + str = ft_calloc(len - *j + 1, sizeof(char)); if (str == NULL) return (str); i = 0; @@ -62,17 +62,18 @@ static char *ft_superdup(char const *s, char c, size_t *j) return (str); } -static void *ft_splitdestroy(char **split) +void *ft_splitdestroy(char **split) { size_t i; i = 0; while (split[i] != NULL) { - free(split[i]); + ft_free(split[i]); i++; } - free(split); + if (split != NULL) + ft_free(split); return (NULL); } @@ -83,8 +84,6 @@ char **ft_split(char const *s, char c) size_t words; char **split; - /*if (!s) - return (NULL);*/ i = 0; j = 0; words = ft_countwords(s, c); diff --git a/super_libft/srcs/ft_strcmp.c b/super_libft/srcs/ft_strcmp.c new file mode 100644 index 0000000..ac395c9 --- /dev/null +++ b/super_libft/srcs/ft_strcmp.c @@ -0,0 +1,27 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strncmp.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: beroy +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/11/07 15:26:26 by beroy #+# #+# */ +/* Updated: 2023/11/07 15:31:01 by beroy ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../libft.h" + +int ft_strcmp(char *s1, const char *s2) +{ + size_t i; + + i = 0; + while (s1[i] != 0 || s2[i] != 0) + { + if (s1[i] != s2[i]) + return (((unsigned char *)s1)[i] - ((unsigned char *)s2)[i]); + i++; + } + return (0); +} diff --git a/super_libft/srcs/ft_strdup.c b/super_libft/srcs/ft_strdup.c index 60dcfb3..67d9fbf 100644 --- a/super_libft/srcs/ft_strdup.c +++ b/super_libft/srcs/ft_strdup.c @@ -19,7 +19,7 @@ char *ft_strdup(const char *s) char *ptr; size = ft_strlen((char *)s); - ptr = malloc((size + 1) * sizeof(char)); + ptr = ft_calloc(size + 1, sizeof(char)); if (ptr == NULL) return (ptr); i = 0; diff --git a/super_libft/srcs/ft_strlen.c b/super_libft/srcs/ft_strlen.c index 823f6c8..e81aa89 100644 --- a/super_libft/srcs/ft_strlen.c +++ b/super_libft/srcs/ft_strlen.c @@ -17,7 +17,7 @@ size_t ft_strlen(const char *str) size_t i; i = 0; - while (str[i]) + while (str && str[i]) i++; return (i); } diff --git a/super_libft/srcs/ft_strncmp.c b/super_libft/srcs/ft_strncmp.c index 1012c81..f23b1b7 100644 --- a/super_libft/srcs/ft_strncmp.c +++ b/super_libft/srcs/ft_strncmp.c @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* ft_strncmp.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: beroy +#+ +:+ +#+ */ +/* By: grebrune +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/11/07 15:26:26 by beroy #+# #+# */ -/* Updated: 2023/11/07 15:31:01 by beroy ### ########.fr */ +/* Updated: 2024/05/13 16:09:49 by grebrune ### ########.fr */ /* */ /* ************************************************************************** */ @@ -17,7 +17,7 @@ int ft_strncmp(char *s1, const char *s2, size_t n) size_t i; i = 0; - while ((s1[i] != 0 || s2[i] != 0) && i < n) + while ((s1[i] != 0 || s2[i] != 0) && (i < n)) { if (s1[i] != s2[i]) return (((unsigned char *)s1)[i] - ((unsigned char *)s2)[i]); diff --git a/super_libft/srcs/ft_strstr.c b/super_libft/srcs/ft_strstr.c new file mode 100644 index 0000000..0f16255 --- /dev/null +++ b/super_libft/srcs/ft_strstr.c @@ -0,0 +1,35 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strstr.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: grebrune +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/09/17 22:00:15 by grebrune #+# #+# */ +/* Updated: 2023/09/20 20:43:40 by grebrune ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "../libft.h" + +char *ft_strstr(char *str, char *to_find) +{ + int i; + int x; + + i = 0; + while (str[i] != '\0') + { + x = 0; + while (str[i + x] == to_find[x] && to_find[x] != '\0') + { + x++; + } + if (to_find[x] == '\0') + return (str + i); + i++; + } + if (str[0] == '\0' && to_find[0] == '\0') + return (str); + return (0); +} diff --git a/super_libft/srcs/ft_substr.c b/super_libft/srcs/ft_substr.c index e35f235..60c600c 100644 --- a/super_libft/srcs/ft_substr.c +++ b/super_libft/srcs/ft_substr.c @@ -23,7 +23,7 @@ char *ft_substr(char const *s, unsigned int start, size_t len) i++; if (len > ft_strlen((char *)s) - i) len = ft_strlen((char *)s) - i; - str = malloc((len + 1) * sizeof(char)); + str = ft_calloc(len + 1, sizeof(char)); if (str == NULL) return (str); j = 0;