From 78dc50a2bce3c6e31405437189e2990d8fc720ac Mon Sep 17 00:00:00 2001 From: Christopher Uhlig Date: Mon, 13 Jan 2025 11:06:54 +0100 Subject: [PATCH] here --- Makefile | 8 +- include/env.h | 18 ++++- include/minishell.h | 16 ++-- lib/libft/Makefile | 3 + lib/libft/ft_strcat.c | 29 ++++++++ lib/libft/ft_strcmp.c | 23 ++++++ lib/libft/ft_strcpy.c | 25 +++++++ lib/libft/libft.h | 5 +- src/builtins_part_one.c | 161 ++++++++++++++++++++++++++++++++++++++++ src/builtins_part_two.c | 84 +++++++++++++++++++++ src/collect_redirs.c | 127 ++++++++++++++++++------------- src/env.c | 16 +++- src/env_to_strlst.c | 58 +++++++++++++++ src/execute_cmd.c | 77 +++++++++++++++++++ src/format_string.c | 125 +++++++++++++++++++++++++++++++ src/get_cmd_path.c | 82 ++++++++++++++++++++ src/interpreter.c | 159 +++++++++++++++++++++++++++++++++++++++ src/main.c | 12 ++- src/parse_cmd.c | 21 ++++-- src/parser.c | 19 ++--- src/repl.c | 30 +++++++- src/tokenizer.c | 4 +- 22 files changed, 1017 insertions(+), 85 deletions(-) create mode 100644 lib/libft/ft_strcat.c create mode 100644 lib/libft/ft_strcmp.c create mode 100644 lib/libft/ft_strcpy.c create mode 100644 src/builtins_part_one.c create mode 100644 src/builtins_part_two.c create mode 100644 src/env_to_strlst.c create mode 100644 src/execute_cmd.c create mode 100644 src/format_string.c create mode 100644 src/get_cmd_path.c create mode 100644 src/interpreter.c diff --git a/Makefile b/Makefile index 827c317..7cfc894 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,10 @@ ################################## VARIABLES ################################### ################################################################################ +################################################################################ +################################## VARIABLES ################################### +################################################################################ + NAME := minishell CC = cc @@ -13,7 +17,9 @@ HEADERS = -I include -I $(LIB_DIR)/libft VPATH := src SRC := main.c debug_tools.c init.c signal_handling.c repl.c new_token.c \ free_token.c new_node.c free_node.c tokenizer.c parser.c \ - parse_cmd.c collect_redirs.c print_ast.c + parse_cmd.c collect_redirs.c print_ast.c interpreter.c env.c \ + get_cmd_path.c env_to_strlst.c execute_cmd.c format_string.c \ + builtins_part_one.c builtins_part_two.c OBJ_DIR := _obj OBJ := $(addprefix $(OBJ_DIR)/, $(SRC:%.c=%.o)) diff --git a/include/env.h b/include/env.h index 5a65333..d38ed29 100644 --- a/include/env.h +++ b/include/env.h @@ -6,10 +6,15 @@ /* By: chuhlig +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/08/08 16:53:39 by dkaiser #+# #+# */ -/* Updated: 2024/10/17 15:37:32 by chuhlig ### ########.fr */ +/* Updated: 2024/12/24 16:21:50 by chuhlig ### ########.fr */ /* */ /* ************************************************************************** */ +#ifndef ENV_H +# define ENV_H +# include "libft.h" +# include + typedef struct s_env { char *name; @@ -19,4 +24,15 @@ typedef struct s_env void getenvlst(t_env **env, char **en); void free_envlst(t_env **env); +char *env_get(t_env *env, char *name); +char **env_to_strlst(t_env *env); +void update_oldpwd(t_env **env); +void update_pwd(t_env **env); +int unset(char **av, t_env **env); +int export(char **av, t_env **env); +int echo(char **av); +int pwd(t_env *env); +int cd(t_env **env, char **args); +int ft_env(t_env *env); +#endif \ No newline at end of file diff --git a/include/minishell.h b/include/minishell.h index 6997b15..028a4fc 100644 --- a/include/minishell.h +++ b/include/minishell.h @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* minishell.h :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: dkaiser +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/06/22 17:14:49 by dkaiser #+# #+# */ -/* Updated: 2024/08/11 12:22:07 by dkaiser ### ########.fr */ +/* Updated: 2025/01/11 16:05:11 by chuhlig ### ########.fr */ /* */ /* ************************************************************************** */ @@ -29,11 +29,17 @@ int init(void); int init_signal_handling(void); -void repl(const char *prompt); +void repl(const char *prompt, t_env **env); -t_list *parse(t_token *tokens); -t_node *parse_cmd(t_token *tokens); +t_list *parse(t_token *tokens, t_env **env); +t_node *parse_cmd(t_token *tokens, t_env **env); t_redirection *collect_redirs(t_token **tokens); void print_ast(t_node *ast); +int eval(t_node *node, t_env **env); +char *get_cmd_path(char *cmd, t_env *env); +int execute_cmd(t_cmd *cmd, t_env **env); +char *format_string(char *str, t_env *env); + + #endif diff --git a/lib/libft/Makefile b/lib/libft/Makefile index 6f2950c..2150e99 100644 --- a/lib/libft/Makefile +++ b/lib/libft/Makefile @@ -26,6 +26,8 @@ SRC = ft_atoi.c \ ft_strdup.c \ ft_striteri.c \ ft_strjoin.c \ + ft_strcat.c \ + ft_strcpy.c \ ft_strlcat.c \ ft_strlcpy.c \ ft_strlen.c \ @@ -45,6 +47,7 @@ SRC = ft_atoi.c \ get_next_line.c \ get_next_line_utils.c \ ft_atol.c \ + ft_strcmp.c \ ft_lstnew_bonus.c \ ft_lstadd_front_bonus.c \ ft_lstsize_bonus.c \ diff --git a/lib/libft/ft_strcat.c b/lib/libft/ft_strcat.c new file mode 100644 index 0000000..648c184 --- /dev/null +++ b/lib/libft/ft_strcat.c @@ -0,0 +1,29 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strcat.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: chuhlig +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/01/09 13:06:44 by chuhlig #+# #+# */ +/* Updated: 2025/01/09 13:07:15 by chuhlig ### ########.fr */ +/* */ +/* ************************************************************************** */ + +char *ft_strcat(char *dest, char *src) +{ + int i; + int j; + + j = 0; + i = 0; + while (dest[i]) + i++; + while (src[j]) + { + dest[i + j] = src[j]; + j++; + } + dest[i + j] = '\0'; + return (dest); +} \ No newline at end of file diff --git a/lib/libft/ft_strcmp.c b/lib/libft/ft_strcmp.c new file mode 100644 index 0000000..af7b2a1 --- /dev/null +++ b/lib/libft/ft_strcmp.c @@ -0,0 +1,23 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strcmp.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: chuhlig +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/12/18 19:03:14 by chuhlig #+# #+# */ +/* Updated: 2024/12/18 19:05:01 by chuhlig ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +int ft_strcmp(char *s1, char *s2) +{ + int i; + + i = 0; + while (s1[i] && s1[i] == s2[i]) + i++; + return (s1[i] - s2[i]); +} \ No newline at end of file diff --git a/lib/libft/ft_strcpy.c b/lib/libft/ft_strcpy.c new file mode 100644 index 0000000..b5c612f --- /dev/null +++ b/lib/libft/ft_strcpy.c @@ -0,0 +1,25 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strcpy.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: chuhlig +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/01/09 14:38:30 by chuhlig #+# #+# */ +/* Updated: 2025/01/09 14:38:53 by chuhlig ### ########.fr */ +/* */ +/* ************************************************************************** */ + +char *ft_strcpy(char *dest, char *src) +{ + int i; + + i = 0; + while (src[i] != '\0') + { + dest[i] = src[i]; + i++; + } + dest[i] = '\0'; + return (dest); +} \ No newline at end of file diff --git a/lib/libft/libft.h b/lib/libft/libft.h index abb739d..6b4c824 100644 --- a/lib/libft/libft.h +++ b/lib/libft/libft.h @@ -6,7 +6,7 @@ /* By: chuhlig +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/03/10 16:37:54 by dkaiser #+# #+# */ -/* Updated: 2024/08/11 14:01:57 by chuhlig ### ########.fr */ +/* Updated: 2025/01/09 14:39:28 by chuhlig ### ########.fr */ /* */ /* ************************************************************************** */ @@ -26,6 +26,7 @@ int ft_isalnum(int c); int ft_isprint(int c); int ft_isspace(char c); int ft_isascii(int c); +int ft_strcmp(char *s1, char *s2); int ft_strlen(const char *str); void *ft_memset(void *b, int c, size_t len); void ft_bzero(void *s, size_t n); @@ -59,6 +60,8 @@ void ft_putstr_fd(char *s, int fd); void ft_putendl_fd(char *s, int fd); void ft_putnbr_fd(int n, int fd); char *ft_strncpy(char *s1, char *s2, int n); +char *ft_strcat(char *dest, char *src); +char *ft_strcpy(char *dest, char *src); typedef struct s_list { diff --git a/src/builtins_part_one.c b/src/builtins_part_one.c new file mode 100644 index 0000000..d64bb54 --- /dev/null +++ b/src/builtins_part_one.c @@ -0,0 +1,161 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* builtins_part_one.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: chuhlig +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/09 17:01:16 by chuhlig #+# #+# */ +/* Updated: 2025/01/10 14:36:55 by chuhlig ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "env.h" + +int echo(char **av) +{ + int i; + int f; + + i = 1; + f = 1; + if (av[1] == NULL || av[1][0] == '\0') + { + write(1, "\n", 1); + return (1); + } + if (ft_strncmp(av[1], "-n", 3) == 0) + { + i++; + f = 0; + } + while (av[i]) + { + write(1, av[i], ft_strlen(av[i])); + i++; + if (av[i]) + write(1, " ", 1); + } + if (f) + write(1, "\n", 1); + return (0); +} + +int pwd(t_env *env) +{ + while (env) + { + if (ft_strncmp(env->name, "PWD", 4) == 0) + { + ft_printf("%s\n", env->value); + break ; + } + env = env->next; + } + return (0); +} + +int ft_env(t_env *env) +{ + while (env != NULL) + { + printf("%s", env->name); + printf("=%s\n", env->value); + env = env->next; + } + return (0); +} + +// int exit(char *av) +// { +// freenode free toke free sequence stop repl free env; +// clear history; +// } +//// + +void free_env_node(t_env *node) +{ + free(node->name); + free(node->value); + free(node); +} + +int unset(char **av, t_env **env) +{ + t_env *current; + t_env *prev; + int i; + + i = 0; + while (av[++i]) + { + current = *env; + prev = NULL; + while (current) + { + if (ft_strcmp(current->name, av[i]) == 0) + { + if (prev) + prev->next = current->next; + else + *env = current->next; + free_env_node(current); + break ; + } + prev = current; + current = current->next; + } + } + return (0); +} + +t_env *env_new(char *name) +{ + t_env *result; + + result = malloc(sizeof(t_env)); + if (!result) + return (NULL); + result->name = name; + return (result); +} + +t_env *check_existing(t_env *env, char *av) +{ + while (env) + { + if (ft_strcmp(env->name, av) == 0) + return (env); + env = env->next; + } + return (NULL); +} + +int export(char **av, t_env **env) +{ + char *tmp; + t_env *current; + int i; + + current = NULL; + i = 0; + while (av[++i]) + { + if ((ft_strchr(av[i], '='))) + { + tmp = ft_strchr(av[i], '='); + *tmp = '\0'; + current = check_existing(*env, av[i]); + if (current) + free(current->value); + else + { + current = env_new(ft_strdup(av[i])); + current->next = *env; + *env = current; + } + current->value = ft_strdup(tmp + 1); + } + } + return (0); +} \ No newline at end of file diff --git a/src/builtins_part_two.c b/src/builtins_part_two.c new file mode 100644 index 0000000..f54e04f --- /dev/null +++ b/src/builtins_part_two.c @@ -0,0 +1,84 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* builtins_part_two.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: chuhlig +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/10/25 20:52:16 by chuhlig #+# #+# */ +/* Updated: 2024/12/20 18:53:03 by chuhlig ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "env.h" + +void update_oldpwd(t_env **env) +{ + t_env *current; + t_env *prev; + char cwd[1028]; + char *tmp; + + prev = NULL; + current = *env; + while (current) + { + if (ft_strncmp(current->name, "OLDPWD", 6) == 0) + break ; + prev = current; + current = current->next; + } + getcwd(cwd, sizeof(cwd)); + tmp = ft_strdup(cwd); + free(current->value); + current->value = tmp; +} + +void update_pwd(t_env **env) +{ + t_env *current; + t_env *prev; + char cwd[1028]; + char *tmp; + + prev = NULL; + current = *env; + while (current) + { + if (ft_strncmp(current->name, "PWD", 3) == 0) + break ; + prev = current; + current = current->next; + } + getcwd(cwd, sizeof(cwd)); + tmp = ft_strdup(cwd); + free(current->value); + current->value = tmp; +} + +int cd(t_env **env, char **av) +{ + t_env *current; + + current = *env; + if (av[1] == NULL) + { + update_oldpwd(env); + while (current) + { + if (ft_strncmp(current->name, "HOME", 4) == 0) + break ; + current = current->next; + } + if (chdir(current->value) == -1) + return (1); + } + else + { + update_oldpwd(env); + if (chdir(av[1]) == -1) + return (1); + update_pwd(env); + } + return (0); +} diff --git a/src/collect_redirs.c b/src/collect_redirs.c index 9ac1605..be0e00f 100644 --- a/src/collect_redirs.c +++ b/src/collect_redirs.c @@ -3,21 +3,61 @@ /* ::: :::::::: */ /* collect_redirs.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: dkaiser +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/08/02 13:49:31 by dkaiser #+# #+# */ -/* Updated: 2024/09/17 19:48:48 by dkaiser ### ########.fr */ +/* Updated: 2025/01/13 09:52:00 by chuhlig ### ########.fr */ /* */ /* ************************************************************************** */ #include "minishell.h" -static t_token *collect_redir(t_token **tokens, t_redirection *result, - t_token *cur); -static void collect_and_check_redir(t_token **tokens, t_redirection *result, - t_token **cur); +static void collect_and_check_redir(t_redirection *result, t_token **cur); static void set_redir(t_redirection *redir, int type, char *specifier); -static int is_output_redir(int i); + +static char *read_heredoc(char *delimiter) +{ + char *line; + char *result; + char *temp; + size_t total_length; + size_t line_length; + + total_length = 0; + result = NULL; + while (1) + { + line = readline("> "); + if (!line || ft_strcmp(line, delimiter) == 0) + { + free(line); + break ; + } + line_length = ft_strlen(line) + 1; + temp = malloc(total_length + line_length + 1); + if (!temp) + { + perror("malloc"); + free(result); + return (NULL); + } + if (result) + { + ft_strcpy(temp, result); + free(result); + } + else + { + temp[0] = '\0'; + } + ft_strcat(temp, line); + ft_strcat(temp, "\n"); + result = temp; + total_length += line_length; + free(line); + } + return (result); +} t_redirection *collect_redirs(t_token **tokens) { @@ -33,7 +73,7 @@ t_redirection *collect_redirs(t_token **tokens) while (cur != NULL && cur->next != NULL) { if (cur->type == REDIR_TOKEN && cur->next->type == STRING_TOKEN) - collect_and_check_redir(tokens, result, &cur); + collect_and_check_redir(result, &cur); else if (cur->type == REDIR_TOKEN) return (free(result), NULL); else @@ -44,56 +84,43 @@ t_redirection *collect_redirs(t_token **tokens) return (result); } -static void collect_and_check_redir(t_token **tokens, t_redirection *result, - t_token **cur) -{ - int is_redir_only; - - is_redir_only = 0; - if ((*cur)->previous == NULL && (*cur)->next->next == NULL) - is_redir_only = 1; - *cur = collect_redir(tokens, result, *cur); - if (is_redir_only) - *tokens = NULL; -} - -static t_token *collect_redir(t_token **tokens, t_redirection *result, - t_token *cur) -{ - set_redir(&result[is_output_redir(cur->content.redir_type)], - cur->content.redir_type, cur->next->content.string); - cur = cur->next; - free_token_and_connect(cur->previous); - if (cur->next != NULL) - { - if (cur->previous == NULL) - *tokens = cur->next; - cur = cur->next; - free_token_and_connect(cur->previous); - } - else - { - free_token(cur); - return (NULL); - } - return (cur); -} - static void set_redir(t_redirection *redir, int type, char *specifier) { redir->type = type; redir->specifier = specifier; } -static int is_output_redir(int i) +static void collect_and_check_redir(t_redirection *result, t_token **cur) { - if (i & (INPUT_FILE | INPUT_LIMITER)) - return (0); - else if (i & (OUTPUT_APPEND | OUTPUT_OVERRIDE)) - return (1); + char *heredoc_data; + t_token *next_token; + + heredoc_data = NULL; + if ((*cur)->content.redir_type == INPUT_LIMITER) + { + heredoc_data = read_heredoc((*cur)->next->content.string); + if (!heredoc_data) + { + perror("Heredoc allocation failed"); + return ; + } + set_redir(&result[0], INPUT_LIMITER, heredoc_data); + } + else if ((*cur)->content.redir_type == INPUT_FILE) + set_redir(&result[0], INPUT_FILE, ft_strdup((*cur)->next->content.string)); + else if ((*cur)->content.redir_type == OUTPUT_OVERRIDE) + set_redir(&result[1], OUTPUT_OVERRIDE, ft_strdup((*cur)->next->content.string)); + else if ((*cur)->content.redir_type == OUTPUT_APPEND) + set_redir(&result[1], OUTPUT_APPEND, ft_strdup((*cur)->next->content.string)); else + printf("Unknown redirection type encountered\n"); + next_token = (*cur)->next; + free_token_and_connect(*cur); + if (next_token) { - panic(UNREACHABLE); - return (-1); + *cur = next_token->next; + free_token_and_connect(next_token); } + else + *cur = NULL; } diff --git a/src/env.c b/src/env.c index 8105bf4..0213209 100644 --- a/src/env.c +++ b/src/env.c @@ -6,11 +6,12 @@ /* By: chuhlig +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/10/17 14:31:07 by chuhlig #+# #+# */ -/* Updated: 2024/10/17 15:18:44 by chuhlig ### ########.fr */ +/* Updated: 2024/12/17 19:36:14 by chuhlig ### ########.fr */ /* */ /* ************************************************************************** */ #include "env.h" +#include void getenvlst(t_env **env, char **en) { @@ -22,7 +23,7 @@ void getenvlst(t_env **env, char **en) while (en[i] != NULL) { tmp = ft_strchr(en[i], '='); - tmp = '\0'; + *tmp = '\0'; current = *env; current = malloc(sizeof(t_env)); current->name = ft_strdup(en[i]); @@ -47,4 +48,15 @@ void free_envlst(t_env **env) free(cur); cur = new; } +} + +char *env_get(t_env *env, char *name) +{ + while (env != NULL) + { + if (!ft_strncmp(env->name, name, ft_strlen(name))) + return (env->value); + env = env->next; + } + return (NULL); } \ No newline at end of file diff --git a/src/env_to_strlst.c b/src/env_to_strlst.c new file mode 100644 index 0000000..c4c98c3 --- /dev/null +++ b/src/env_to_strlst.c @@ -0,0 +1,58 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* env_to_strlst.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: chuhlig +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/12/17 19:22:28 by chuhlig #+# #+# */ +/* Updated: 2024/12/17 19:22:36 by chuhlig ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" +#include "minishell.h" + +static char *get_var_assign(t_env *cur); + +char **env_to_strlst(t_env *env) +{ + int size; + t_env *cur; + char **result; + int i; + + size = 0; + cur = env; + while (cur != NULL) + { + size++; + cur = cur->next; + } + result = malloc(sizeof(char *) * (size + 1)); + if (result == NULL) + return (NULL); + i = 0; + cur = env; + while (i < size) + { + result[i] = get_var_assign(cur); + cur = cur->next; + i++; + } + result[i] = NULL; + return (result); +} + +static char *get_var_assign(t_env *cur) +{ + char *left_side; + char *result; + + left_side = ft_strjoin(cur->name, "="); + if (left_side == NULL) + return (NULL); + result = ft_strjoin(left_side, cur->value); + free(left_side); + return (result); +} \ No newline at end of file diff --git a/src/execute_cmd.c b/src/execute_cmd.c new file mode 100644 index 0000000..803d88f --- /dev/null +++ b/src/execute_cmd.c @@ -0,0 +1,77 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* execute_cmd.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: chuhlig +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/12/17 19:21:35 by chuhlig #+# #+# */ +/* Updated: 2025/01/13 09:50:56 by chuhlig ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" +#include +#include +#include +#include +#include +#include + +int execute_cmd(t_cmd *cmd, t_env **env) +{ + char *cmd_path; + pid_t pid; + int status; + int result; + int original_stdout; + int original_stdin; + + original_stdout = dup(STDOUT_FILENO); + original_stdin = dup(STDIN_FILENO); + if (handle_redirections(cmd->redirs) == -1) + { + dup2(original_stdout, STDOUT_FILENO); + dup2(original_stdin, STDIN_FILENO); + close(original_stdout); + close(original_stdin); + return (EXIT_FAILURE); + } + if (is_builtin(cmd->args[0])) + { + result = execute_builtin(cmd->args, env); + dup2(original_stdout, STDOUT_FILENO); + dup2(original_stdin, STDIN_FILENO); + close(original_stdout); + close(original_stdin); + return (result); + } + pid = fork(); + if (pid == -1) + { + perror("fork"); + dup2(original_stdout, STDOUT_FILENO); + dup2(original_stdin, STDIN_FILENO); + close(original_stdout); + close(original_stdin); + return (EXIT_FAILURE); + } + if (pid == 0) + { + cmd_path = get_cmd_path(cmd->args[0], *env); + if (!cmd_path) + { + printf("%s: command not found\n", cmd->args[0]); + exit(EXIT_FAILURE); + } + execve(cmd_path, cmd->args, env_to_strlst(*env)); + perror("execve"); + exit(EXIT_FAILURE); + } + waitpid(pid, &status, 0); + dup2(original_stdout, STDOUT_FILENO); + dup2(original_stdin, STDIN_FILENO); + close(original_stdout); + close(original_stdin); + return (WEXITSTATUS(status)); +} \ No newline at end of file diff --git a/src/format_string.c b/src/format_string.c new file mode 100644 index 0000000..bd7f703 --- /dev/null +++ b/src/format_string.c @@ -0,0 +1,125 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* format_string.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: chuhlig +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/12/17 19:30:11 by chuhlig #+# #+# */ +/* Updated: 2024/12/17 19:31:54 by chuhlig ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "get_next_line.h" +#include "libft.h" +#include "minishell.h" + +static void append_slice(char **dst, char *src, int start, int end); +static void append_var(char **dst, char *src, int *pos, t_env *env); + +enum e_format_mode +{ + LITERAL = 1, + VARIABLE = 2, +}; + +char *format_string(char *str, t_env *env) +{ + char *result; + int pos; + int start; + int mode; + + pos = 0; + start = 0; + mode = 0; + result = NULL; + if (str == NULL) + return (NULL); + while (str[pos] != '\0') + { + if (str[pos] == '\'') + { + append_slice(&result, str, start, pos); + start = pos + 1; + mode ^= LITERAL; + } + if (str[pos] == '"' && !(mode & LITERAL)) + { + append_slice(&result, str, start, pos); + start = pos + 1; + } + if (str[pos] == '$' && !(mode & LITERAL)) + { + append_slice(&result, str, start, pos); + append_var(&result, str, &pos, env); + start = pos; + continue ; + } + pos++; + } + append_slice(&result, str, start, pos); + return (result); +} + +static void append_slice(char **dst, char *src, int start, int end) +{ + char *result; + int len; + int i; + + if (*dst != NULL) + len = ft_strlen(*dst); + else + { + len = 0; + } + result = malloc(len + (end - start) + 1); + if (!result) + return ; + ft_strncpy(result, *dst, len); + i = 0; + while (start + i < end) + { + result[len + i] = src[start + i]; + i++; + } + result[len + i] = '\0'; + if (*dst != NULL) + free(*dst); + *dst = result; +} + +static void append_var(char **dst, char *src, int *pos, t_env *env) +{ + int i; + char *var; + char *value; + char *result; + + i = 0; + *pos += 1; + while (src[*pos + i] != '\0' && src[*pos + i] != '\'' && src[*pos + + i] != '"' && src[*pos + i] != '$') + { + i++; + } + var = malloc(i + 1); + if (var == NULL) + return ; + var[i] = '\0'; + i--; + while (i >= 0) + { + var[i] = src[*pos + i]; + i--; + } + value = env_get(env, var); + if (value != NULL) + { + result = ft_strjoin(*dst, value); + free(*dst); + *dst = result; + } + *pos += ft_strlen(var); +} diff --git a/src/get_cmd_path.c b/src/get_cmd_path.c new file mode 100644 index 0000000..8a27584 --- /dev/null +++ b/src/get_cmd_path.c @@ -0,0 +1,82 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* get_cmd_path.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: chuhlig +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/12/17 19:19:59 by chuhlig #+# #+# */ +/* Updated: 2024/12/17 19:20:08 by chuhlig ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" +#include "minishell.h" + +static char *get_absolute_cmd_path(char *cmd, t_env *env); +static char *find_in_path(char *cmd, t_env *env); +char **get_split_path(t_env *env); + +char *get_cmd_path(char *cmd, t_env *env) +{ + if (cmd[0] == '/') + return (ft_strdup(cmd)); + else if (ft_strchr(cmd, '/')) + return (get_absolute_cmd_path(cmd, env)); + else + return (find_in_path(cmd, env)); +} + +static char *get_absolute_cmd_path(char *cmd, t_env *env) +{ + char *cur_dir; + char *result; + + cur_dir = ft_strjoin(env_get(env, "PWD"), "/"); + if (!cur_dir) + return (NULL); + result = ft_strjoin(cur_dir, cmd); + free(cur_dir); + if (!result) + return (NULL); + if (access(result, X_OK) == -1) + { + free(result); + return (NULL); + } + return (result); +} + +static char *find_in_path(char *cmd, t_env *env) +{ + char *cur_path; + char *cmd_path; + char **path; + + path = get_split_path(env); + cmd_path = NULL; + while (*path) + { + if (cmd_path) + free(cmd_path); + cur_path = ft_strjoin(*path, "/"); + if (!cur_path) + return (NULL); + cmd_path = ft_strjoin(cur_path, cmd); + free(cur_path); + if (!cmd_path) + return (NULL); + if (access(cmd_path, X_OK) != -1) + return (cmd_path); + path++; + } + return (NULL); +} + +char **get_split_path(t_env *env) +{ + char *path; + + path = env_get(env, "PATH"); + return (ft_split(path, ':')); +} diff --git a/src/interpreter.c b/src/interpreter.c new file mode 100644 index 0000000..7b0306f --- /dev/null +++ b/src/interpreter.c @@ -0,0 +1,159 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* interpreter.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: chuhlig +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/12/17 19:15:49 by chuhlig #+# #+# */ +/* Updated: 2025/01/13 09:53:33 by chuhlig ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "debug_tools.h" +#include "minishell.h" +#include +#include +#include +#include +#include +#include +#include + +int is_builtin(char *cmd) +{ + return ((ft_strcmp(cmd, "export") == 0) + || (ft_strcmp(cmd, "unset") == 0) + || (ft_strcmp(cmd, "cd") == 0) + || (ft_strcmp(cmd, "exit") == 0) + || (ft_strcmp(cmd, "echo") == 0) + || (ft_strcmp(cmd, "pwd") == 0) + || (ft_strcmp(cmd, "env") == 0)); +} + +int execute_builtin(char **args, t_env **env) +{ + if (ft_strcmp(args[0], "export") == 0) + return (export(args, env)); + else if (ft_strcmp(args[0], "unset") == 0) + return (unset(args, env)); + else if (ft_strcmp(args[0], "cd") == 0) + return (cd(env, args)); + else if (ft_strcmp(args[0], "exit") == 0) + return (EXIT_SUCCESS); + else if (ft_strcmp(args[0], "echo") == 0) + return (echo(args)); + else if (ft_strcmp(args[0], "pwd") == 0) + return (pwd(*env)); + else if (ft_strcmp(args[0], "env") == 0) + return (ft_env(*env)); + return (1); +} + +static int handle_redirections(t_redirection *redirs) +{ + int fd; + + if (redirs[0].type == INPUT_FILE) + { + fd = open(redirs[0].specifier, O_RDONLY); + if (fd < 0) + { + perror("open"); + return (-1); + } + dup2(fd, STDIN_FILENO); + close(fd); + } + else if (redirs[0].type == INPUT_LIMITER) + { + fd = open("/tmp/heredoc_tmp", O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd < 0) + { + perror("open"); + return (-1); + } + write(fd, redirs[0].specifier, ft_strlen(redirs[0].specifier)); + close(fd); + fd = open("/tmp/heredoc_tmp", O_RDONLY); + if (fd < 0) + { + perror("open"); + return (-1); + } + dup2(fd, STDIN_FILENO); + close(fd); + } + if (redirs[1].type == OUTPUT_OVERRIDE) + { + fd = open(redirs[1].specifier, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd < 0) + { + perror("open"); + return (-1); + } + dup2(fd, STDOUT_FILENO); + close(fd); + } + else if (redirs[1].type == OUTPUT_APPEND) + { + fd = open(redirs[1].specifier, O_WRONLY | O_CREAT | O_APPEND, 0644); + if (fd < 0) + { + perror("open"); + return (-1); + } + dup2(fd, STDOUT_FILENO); + close(fd); + } + return (0); + } + +static int eval_rec(t_node *node, t_env **env, int in_fd) +{ + pid_t pid; + int p[2]; + int result; + int status; + int original_stdin; + + if (node->type == PIPE_NODE) + { + pipe(p); + pid = fork(); + if (pid == 0) + { + close(p[0]); + dup2(in_fd, STDIN_FILENO); + dup2(p[1], STDOUT_FILENO); + result = eval_rec(node->content.pipe.left, env, in_fd); + exit(result); + } + else + { + close(p[1]); + original_stdin = dup(STDIN_FILENO); + dup2(p[0], STDIN_FILENO); + result = eval_rec(node->content.pipe.right, env, p[0]); + waitpid(pid, &status, 0); + dup2(original_stdin, STDIN_FILENO); + close(original_stdin); + } + } + else if (node->type == CMD_NODE) + { + result = execute_cmd(&node->content.cmd, env); + } + else + { + printf("Handling unknown node type\n"); + panic("UNREACHABLE"); + result = EXIT_FAILURE; + } + return (result); +} + +int eval(t_node *node, t_env **env) +{ + return (eval_rec(node, env, STDIN_FILENO)); +} diff --git a/src/main.c b/src/main.c index 8523b9e..a53760c 100644 --- a/src/main.c +++ b/src/main.c @@ -6,15 +6,21 @@ /* By: chuhlig +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/06/22 17:14:03 by dkaiser #+# #+# */ -/* Updated: 2024/07/18 16:44:14 by chuhlig ### ########.fr */ +/* Updated: 2024/12/17 19:26:42 by chuhlig ### ########.fr */ /* */ /* ************************************************************************** */ #include "../include/minishell.h" -int main(void) +int main(int argc, char *argv[], char *envp[]) { + t_env *env; + + env = NULL; + if (!argc && !argv) + return (1); if (init()) return (1); - repl("Minishell $ "); + getenvlst(&env, envp); + repl("Minishell $ ", &env); } diff --git a/src/parse_cmd.c b/src/parse_cmd.c index 2755cae..3c4eb96 100644 --- a/src/parse_cmd.c +++ b/src/parse_cmd.c @@ -3,28 +3,35 @@ /* ::: :::::::: */ /* parse_cmd.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: dkaiser +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/07/08 15:06:25 by dkaiser #+# #+# */ -/* Updated: 2024/08/11 12:20:06 by dkaiser ### ########.fr */ +/* Updated: 2025/01/11 16:04:50 by chuhlig ### ########.fr */ /* */ /* ************************************************************************** */ #include "minishell.h" -static char **collect_args(t_token **tokens); +static char **collect_args(t_token **tokens, t_env **env); -t_node *parse_cmd(t_token *tokens) +t_node *parse_cmd(t_token *tokens, t_env **env) { char **args; t_redirection *redirs; redirs = collect_redirs(&tokens); - args = collect_args(&tokens); + if (redirs == NULL) + return (NULL); + args = collect_args(&tokens, env); + if (args == NULL) + { + free(redirs); + return (NULL); + } return (new_cmd_node(args, redirs)); } -static char **collect_args(t_token **tokens) +static char **collect_args(t_token **tokens, t_env **env) { t_token *cur; char **result; @@ -43,7 +50,7 @@ static char **collect_args(t_token **tokens) { if (cur->previous) free_token(cur->previous); - result[i] = cur->content.string; + result[i] = format_string(cur->content.string, *env); i++; cur = cur->next; } diff --git a/src/parser.c b/src/parser.c index 06c1df7..1375954 100644 --- a/src/parser.c +++ b/src/parser.c @@ -3,35 +3,36 @@ /* ::: :::::::: */ /* parser.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: dkaiser +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/06/29 15:53:29 by dkaiser #+# #+# */ -/* Updated: 2024/09/17 19:03:48 by dkaiser ### ########.fr */ +/* Updated: 2025/01/11 16:06:54 by chuhlig ### ########.fr */ /* */ /* ************************************************************************** */ #include "libft.h" #include "minishell.h" #include "token.h" +#include "env.h" static t_token *find_token_by_type(t_token *tokens, int type); t_token *split_at_first(t_token **tokens, int type); -static t_node *parse_statement(t_token *tokens); +static t_node *parse_statement(t_token *tokens, t_env **env); -t_list *parse(t_token *tokens) +t_list *parse(t_token *tokens, t_env **env) { t_node *result; if ((*tokens).type == PIPE_TOKEN) result = NULL; else - result = parse_statement(tokens); + result = parse_statement(tokens, env); if (result == NULL) printf("Parsing error.\n"); return (ft_lstnew(result)); } -static t_node *parse_statement(t_token *tokens) +static t_node *parse_statement(t_token *tokens, t_env **env) { t_token *left_side_tokens; @@ -43,12 +44,12 @@ static t_node *parse_statement(t_token *tokens) } else if (tokens != NULL) { - return (new_pipe_node(parse_cmd(left_side_tokens), - parse_statement(tokens))); + return (new_pipe_node(parse_cmd(left_side_tokens, env), + parse_statement(tokens, env))); } else { - return (parse_cmd(left_side_tokens)); + return (parse_cmd(left_side_tokens, env)); } } diff --git a/src/repl.c b/src/repl.c index d590fec..7ff80a8 100644 --- a/src/repl.c +++ b/src/repl.c @@ -6,14 +6,34 @@ /* By: chuhlig +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/06/24 16:07:04 by dkaiser #+# #+# */ -/* Updated: 2024/09/13 16:26:35 by dkaiser ### ########.fr */ +/* Updated: 2025/01/11 16:01:44 by chuhlig ### ########.fr */ /* */ /* ************************************************************************** */ #include "../include/minishell.h" #include "token.h" -void repl(const char *prompt) +t_token *reverse_token_list(t_token *head) +{ + t_token *prev; + t_token *current; + t_token *next; + + prev = NULL; + current = head; + next = NULL; + while (current != NULL) + { + next = current->previous; + current->next = prev; + current->previous = next; + prev = current; + current = next; + } + return (prev); +} + +void repl(const char *prompt, t_env **env) { char *input; t_token *token_list; @@ -29,9 +49,13 @@ void repl(const char *prompt) add_history(input); token_list = NULL; tokenizer(input, &token_list, '\0'); - lines = parse(token_list); + token_list = reverse_token_list(token_list); + lines = parse(token_list, env); if (lines) + { print_ast(lines->content); + eval(lines->content, env); + } free(input); } } diff --git a/src/tokenizer.c b/src/tokenizer.c index ab8a6ac..26edd2e 100644 --- a/src/tokenizer.c +++ b/src/tokenizer.c @@ -6,7 +6,7 @@ /* By: chuhlig +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/06/28 20:55:50 by chuhlig #+# #+# */ -/* Updated: 2024/08/29 15:26:55 by dkaiser ### ########.fr */ +/* Updated: 2025/01/11 15:22:07 by chuhlig ### ########.fr */ /* */ /* ************************************************************************** */ @@ -111,6 +111,4 @@ void tokenizer(char *s, t_token **token_list, char quote_check) pos = i + 1; } } - while ((*token_list)->previous) - *token_list = (*token_list)->previous; } -- 2.47.2