diff options
| author | Dominik Kaiser | 2025-01-20 20:14:32 +0100 |
|---|---|---|
| committer | GitHub | 2025-01-20 20:14:32 +0100 |
| commit | bd8c817797d5f2b1affe6957ffc51846a38e70ec (patch) | |
| tree | 2fc0f567b1c4f2f168a931ad0bff69e52c6c226c | |
| parent | a9aba07b52cbf98eb9c52cd8ee0cd5f5021d2931 (diff) | |
| parent | dc6a4f2d0de92984c2584ef905011e2a60792850 (diff) | |
| download | minishell-bd8c817797d5f2b1affe6957ffc51846a38e70ec.tar.gz minishell-bd8c817797d5f2b1affe6957ffc51846a38e70ec.zip | |
Merge interpreter changes into main
Miau
38 files changed, 1179 insertions, 399 deletions
@@ -2,6 +2,10 @@ ################################## VARIABLES ################################### ################################################################################ +################################################################################ +################################## VARIABLES ################################### +################################################################################ + NAME := minishell CC = cc @@ -14,7 +18,10 @@ 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 interpreter.c env.c \ - get_cmd_path.c env_to_strlst.c execute_cmd.c + get_cmd_path.c env_to_strlst.c execute_cmd.c format_string.c \ + builtins_part_one.c builtins_part_two.c env_tools.c error.c \ + read_heredoc.c create_files.c builtins_part_three.c handle_redir.c \ + praise_the_norme.c OBJ_DIR := _obj OBJ := $(addprefix $(OBJ_DIR)/, $(SRC:%.c=%.o)) @@ -58,7 +65,9 @@ debug: CFLAGS += -g debug: CFLAGS += -fsanitize=address -fsanitize=undefined \ -fno-sanitize-recover=all -fsanitize=float-divide-by-zero \ -fsanitize=float-cast-overflow -fno-sanitize=null \ - -fno-sanitize=alignment + -fno-sanitize=alignment -fno-sanitize=object-size \ + -fno-sanitize=vptr -fno-sanitize=return -fno-sanitize=signed-integer-overflow \ + -fno-sanitize=bounds -fno-sanitize=pointer-subtract -fno-sanitize=pointer-compare debug: CFLAGS += -DDEBUG=1 debug: clean all diff --git a/include/ast.h b/include/ast.h index cd2f9c9..0dede50 100644 --- a/include/ast.h +++ b/include/ast.h @@ -3,15 +3,17 @@ /* ::: :::::::: */ /* ast.h :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */ +/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/06/27 11:48:27 by dkaiser #+# #+# */ -/* Updated: 2024/08/11 12:20:56 by dkaiser ### ########.fr */ +/* Updated: 2025/01/18 19:28:51 by chuhlig ### ########.fr */ /* */ /* ************************************************************************** */ -#include "debug_tools.h" -#include "stdlib.h" +#ifndef AST_H +# define AST_H +# include "debug_tools.h" +# include "stdlib.h" enum e_node_type { @@ -44,6 +46,7 @@ typedef struct s_cmd { char **args; struct s_redirection redirs[2]; + t_list *create_files; } t_cmd; union u_node_content @@ -61,7 +64,10 @@ typedef struct s_node t_node *new_node(int type); t_node *new_pipe_node(t_node *left, t_node *right); -t_node *new_cmd_node(char **args, t_redirection redirs[2]); +t_node *new_cmd_node(char **args, t_redirection redirs[2], + t_list *create_files); t_node *new_string_node(char *string); void free_node(t_node *node); + +#endif
\ No newline at end of file diff --git a/include/debug_tools.h b/include/debug_tools.h index 4a7ff10..a014ff1 100644 --- a/include/debug_tools.h +++ b/include/debug_tools.h @@ -3,17 +3,17 @@ /* ::: :::::::: */ /* debug_tools.h :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */ +/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/06/24 18:34:37 by dkaiser #+# #+# */ -/* Updated: 2024/06/28 15:05:12 by dkaiser ### ########.fr */ +/* Updated: 2025/01/20 17:56:01 by dkaiser ### ########.fr */ /* */ /* ************************************************************************** */ #ifndef DEBUG_TOOLS_H # define DEBUG_TOOLS_H - # include "libft.h" +# include <stdarg.h> # ifndef DEBUG # define DEBUG 0 @@ -22,4 +22,7 @@ void dbg(char *str); void panic(char *msg); + +void dbg2(const char *format, ...); + #endif diff --git a/include/env.h b/include/env.h index a35bec3..bfb28c7 100644 --- a/include/env.h +++ b/include/env.h @@ -6,11 +6,14 @@ /* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/08/08 16:53:39 by dkaiser #+# #+# */ -/* Updated: 2024/10/25 19:53:38 by chuhlig ### ########.fr */ +/* Updated: 2025/01/20 16:48:57 by chuhlig ### ########.fr */ /* */ /* ************************************************************************** */ -#include "libft.h" +#ifndef ENV_H +# define ENV_H +# include "libft.h" +# include <stdio.h> typedef struct s_env { @@ -19,7 +22,22 @@ typedef struct s_env struct s_env *next; } t_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);
\ No newline at end of file +void free_env_node(t_env *node); +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 f); +int echo(char **av); +int pwd(t_env *env); +int cd(t_env **env, char **args); +int ft_env(t_env *env); +int builtin_exit(char **args, t_env **env); +t_env *env_new(char *name); +t_env *check_existing(t_env *env, char *av); +int check_flag(int f); + +#endif diff --git a/include/minishell.h b/include/minishell.h index b2a3845..356df7a 100644 --- a/include/minishell.h +++ b/include/minishell.h @@ -6,7 +6,7 @@ /* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/06/22 17:14:49 by dkaiser #+# #+# */ -/* Updated: 2024/10/25 16:10:21 by chuhlig ### ########.fr */ +/* Updated: 2025/01/20 19:12:03 by chuhlig ### ########.fr */ /* */ /* ************************************************************************** */ @@ -25,19 +25,45 @@ # include <stdlib.h> # include <termios.h> # include <unistd.h> +# include <fcntl.h> int init(void); int init_signal_handling(void); -void repl(const char *prompt, t_env **env); +void repl(const char *prompt, t_env **env, int *promptflag); -t_list *parse(t_token *tokens); -t_node *parse_cmd(t_token *tokens); -t_redirection *collect_redirs(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, t_env *env, t_list **cf); 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 *get_cmd_path(char *cmd, t_env *env, int *return_code); +int execute_cmd(t_cmd *cmd, t_env **env); +char *format_string(char *str, t_env *env, int is_literal); +void set_return_code(int return_code, t_env **env); +int handle_redirections(t_redirection *redirs); +void *error(int err_code, char *err_text, int exit_code, + int *ret_code); +void command_not_found_error(char *cmd); +char *read_heredoc(char *delimiter); +int handle_input_redirection(t_redirection *redir); +int handle_output_redirection(t_redirection *redir); +int handle_redirections(t_redirection *redirs); +int handle_pipe_parent(int p[2], t_node *node, t_env **env); +int handle_pipe_child(int p[2], t_node *node, t_env **env, + int in_fd); +int open_file(char *path, int flags, int mode); +int eval_rec(t_node *node, t_env **env, int in_fd); +int create_files(t_list *files); +void q4fc(t_list **queue, t_redirection *redir); +void i_love_the_norme(t_token **cur, t_token **tokens); + +typedef struct s_minidata +{ + t_env *env; + t_list **create_files; +} t_minidata; + #endif diff --git a/include/token.h b/include/token.h index 7e2038a..2e8da35 100644 --- a/include/token.h +++ b/include/token.h @@ -6,7 +6,7 @@ /* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/06/27 13:27:18 by dkaiser #+# #+# */ -/* Updated: 2024/08/29 15:26:23 by dkaiser ### ########.fr */ +/* Updated: 2025/01/20 19:10:30 by chuhlig ### ########.fr */ /* */ /* ************************************************************************** */ @@ -43,10 +43,11 @@ t_token *new_str_token(char *str, t_token *previous, t_token *next); t_token *new_redir_token(int type, t_token *previous, t_token *next); - +void free_tokens(t_token *tokens); void free_token(t_token *token); - +void free_token_and_connect(t_token *token); void tokenizer(char *s, t_token **token_list, char quote_check); +void print_token(t_token *token); #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..b21235b --- /dev/null +++ b/lib/libft/ft_strcat.c @@ -0,0 +1,29 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strcat.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/01/09 13:06:44 by chuhlig #+# #+# */ +/* Updated: 2025/01/14 14:09:49 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); +} diff --git a/lib/libft/ft_strcmp.c b/lib/libft/ft_strcmp.c new file mode 100644 index 0000000..a319c63 --- /dev/null +++ b/lib/libft/ft_strcmp.c @@ -0,0 +1,23 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strcmp.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/12/18 19:03:14 by chuhlig #+# #+# */ +/* Updated: 2025/01/14 14:09:59 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]); +} diff --git a/lib/libft/ft_strcpy.c b/lib/libft/ft_strcpy.c new file mode 100644 index 0000000..94a07f7 --- /dev/null +++ b/lib/libft/ft_strcpy.c @@ -0,0 +1,25 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strcpy.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/01/09 14:38:30 by chuhlig #+# #+# */ +/* Updated: 2025/01/14 14:10:06 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); +} 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 <chuhlig@student.42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* 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 index 6b92d9c..11989cc 100644 --- a/src/builtins_part_one.c +++ b/src/builtins_part_one.c @@ -6,147 +6,115 @@ /* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/08/09 17:01:16 by chuhlig #+# #+# */ -/* Updated: 2024/10/25 20:52:36 by chuhlig ### ########.fr */ +/* Updated: 2025/01/20 19:07:18 by chuhlig ### ########.fr */ /* */ /* ************************************************************************** */ #include "env.h" +#include <stdio.h> -int echo(char **av) +int unset(char **av, t_env **env) { - int i; - int f; + t_env *current; + t_env *prev; + int i; - i = 1; - f = 1; - if (av[1][0] == '\0') - { - write(1, "\n", 1); - return (1); - } - if (ft_strcmp(av[1], "-n")) - { - i++; - f = 0; - } - while (av[i]) + i = 0; + while (av[++i]) { - write(1, &av[1], ft_strlen(av[i])); - 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; + } } - if (f) - write(1, "\n", 1); return (0); } -int pwd(t_env **env, char *av) +t_env *check_existing(t_env *env, char *av) { - t_env *current; - t_env *prev; - char *tmp; - - current = env; - prev = NULL; - while (current) + while (env) { - if (ft_strcmp(current->name, av == 0)) - break ; - prev = current; - current = current->next; + if (ft_strcmp("$", av) == 0) + return (NULL); + if (ft_strcmp(env->name, av) == 0) + return (env); + env = env->next; } - ft_printf("%s\n", current->value); - return (0); + return (NULL); } -int env(t_env **env) +void export_export(char *av, t_env **env) { + char *tmp; t_env *current; - t_env *prev; - current = env; - prev = NULL; - while (current) + current = NULL; + tmp = ft_strchr(av, '='); + *tmp = '\0'; + current = check_existing(*env, av); + if (current) + free(current->value); + else { - ft_printf("%s", current->name); - ft_printf("=%s\n", current->value); - prev = current; - current = current->next; + current = env_new(ft_strdup(av)); + current->next = *env; + *env = current; } - return (0); + current->value = ft_strdup(tmp + 1); } -int exit(char *av) +int is_valid_identifier(char *str) { - freenode free toke free sequence stop repl free env; - clear history; -} - -int export(char **av, t_env **env) -{ - char *tmp; - t_env *current; - int i; + int i; - i = i; - while (av[i]) + i = 0; + if (!ft_isalpha(str[0]) && str[0] != '_') + return (0); + while (str[i] && str[i] != '=') { - if (t_strchr(av[i], '=')) - { - tmp = ft_strchr(av[i], '='); - tmp = '\0'; - current = *env; - while (current) - { - if (ft_strcmp(current->name, tmp[i]) == 0) - { - free(current->value); - current->value = ft_strdup(tmp + 1); - break ; - } - current = current->next; - } - if (!current) - { - current = malloc(sizeof(t_env)); - current->name = ft_strdup(av[i]); - current->value = ft_strdup(tmp + 1); - current->next = *env; - *env = current; - } - } + if (!ft_isalnum(str[i]) && str[i] != '_') + return (0); i++; } return (1); } -int unset(char **av, t_env **env) +int export(char **av, t_env **env, int f) { - t_env *current; - t_env *prev; + char *equal_sign; int i; i = 0; - current = env; - prev = NULL; - while (av[i]) + while (av[++i]) { - while (current) + equal_sign = ft_strchr(av[i], '='); + if (equal_sign) + *equal_sign = '\0'; + if (!is_valid_identifier(av[i])) { - if (ft_strcmp(current->name, av[i] == 0)) - break ; - prev = current; - current = current->next; + write(1, "Minishell $ export: not a valid identifier\n", 43); + if (equal_sign) + *equal_sign = '='; + f++; + continue ; } - if (current) + if (equal_sign) { - if (prev) - prev->next = current->next; - else - *env = current->next; - free(current->value); - free(current); + *equal_sign = '='; + export_export(av[i], env); } - i++; } - return (0); -}
\ No newline at end of file + return (check_flag(f)); +} diff --git a/src/builtins_part_three.c b/src/builtins_part_three.c new file mode 100644 index 0000000..5f6fa31 --- /dev/null +++ b/src/builtins_part_three.c @@ -0,0 +1,85 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* builtins_part_three.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/01/18 18:29:24 by chuhlig #+# #+# */ +/* Updated: 2025/01/20 17:08:17 by chuhlig ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "env.h" + +void exit_shell(t_env **env, int exit_status) +{ + free_envlst(env); + exit(exit_status); +} + +int builtin_exit(char **av, t_env **env) +{ + int exit_status; + + if (av[1] && !av[2]) + exit_status = ft_atoi(av[1]); + else if (av[2]) + exit_status = 1; + else + exit_status = 0; + exit_shell(env, exit_status); + return (exit_status); +} + +void set_return_code(int return_code, t_env **env) +{ + t_env *cur; + + cur = check_existing(*env, "?"); + if (cur) + free(cur->value); + else + { + cur = env_new(ft_strdup("?")); + cur->next = *env; + *env = cur; + } + cur->value = ft_itoa(return_code); +} + +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 (0); + } + 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 check_flag(int f) +{ + if (f) + return (1); + return (0); +} diff --git a/src/builtins_part_two.c b/src/builtins_part_two.c index 94ef258..e461861 100644 --- a/src/builtins_part_two.c +++ b/src/builtins_part_two.c @@ -6,7 +6,7 @@ /* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/10/25 20:52:16 by chuhlig #+# #+# */ -/* Updated: 2024/10/25 20:52:46 by chuhlig ### ########.fr */ +/* Updated: 2025/01/20 19:12:33 by chuhlig ### ########.fr */ /* */ /* ************************************************************************** */ @@ -19,6 +19,8 @@ void update_oldpwd(t_env **env) char cwd[1028]; char *tmp; + prev = NULL; + current = *env; while (current) { if (ft_strncmp(current->name, "OLDPWD", 6) == 0) @@ -39,6 +41,8 @@ void update_pwd(t_env **env) char cwd[1028]; char *tmp; + prev = NULL; + current = *env; while (current) { if (ft_strncmp(current->name, "PWD", 3) == 0) @@ -55,28 +59,57 @@ void update_pwd(t_env **env) int cd(t_env **env, char **av) { t_env *current; - t_env *prev; - t_env *pwd; - current = env; + current = *env; if (av[1] == NULL) { - update_oldpwd(&env); + update_oldpwd(env); while (current) { if (ft_strncmp(current->name, "HOME", 4) == 0) break ; - prev = current; current = current->next; } if (chdir(current->value) == -1) - return ; + return (1); + update_pwd(env); } else { - update_oldpwd(&env); + update_oldpwd(env); if (chdir(av[1]) == -1) - return ; - update_pwd(&env); + return (1); + update_pwd(env); + } + 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; } -}
\ No newline at end of file + return (0); +} + +int ft_env(t_env *env) +{ + while (env != NULL) + { + if (ft_strchr(env->name, '?')) + { + env = env->next; + continue ; + } + printf("%s", env->name); + printf("=%s\n", env->value); + env = env->next; + } + return (0); +} diff --git a/src/collect_redirs.c b/src/collect_redirs.c index 9ac1605..f274053 100644 --- a/src/collect_redirs.c +++ b/src/collect_redirs.c @@ -3,37 +3,42 @@ /* ::: :::::::: */ /* collect_redirs.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */ +/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/08/02 13:49:31 by dkaiser #+# #+# */ -/* Updated: 2024/09/17 19:48:48 by dkaiser ### ########.fr */ +/* Updated: 2025/01/20 18:39:24 by dkaiser ### ########.fr */ /* */ /* ************************************************************************** */ #include "minishell.h" +#include <stdlib.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 set_redir(t_redirection *redir, int type, char *specifier); -static int is_output_redir(int i); +static void collect_and_check_redir(t_redirection *result, + t_token **cur, t_minidata *data, t_token **tokens); +static t_redirection *set_redir(t_redirection *redir, int type, char *spec, + t_env *env); +static int set_heredoc_data(t_token *cur, t_redirection *result, + t_env *env); -t_redirection *collect_redirs(t_token **tokens) +t_redirection *collect_redirs(t_token **tokens, t_env *env, + t_list **create_files) { t_redirection *result; t_token *cur; + t_minidata data; cur = *tokens; result = malloc(sizeof(t_redirection) * 2); if (result == NULL) return (free_tokens(*tokens), NULL); - set_redir(&result[0], 0, NULL); - set_redir(&result[1], 0, NULL); - while (cur != NULL && cur->next != NULL) + set_redir(&result[0], 0, NULL, env); + set_redir(&result[1], 0, NULL, env); + data.create_files = create_files; + data.env = env; + while (cur != NULL) { if (cur->type == REDIR_TOKEN && cur->next->type == STRING_TOKEN) - collect_and_check_redir(tokens, result, &cur); + collect_and_check_redir(result, &cur, &data, tokens); else if (cur->type == REDIR_TOKEN) return (free(result), NULL); else @@ -44,56 +49,67 @@ t_redirection *collect_redirs(t_token **tokens) return (result); } -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, + t_minidata *data, t_token **tokens) { - int is_redir_only; + char *str; - 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; + if ((*cur)->content.redir_type != INPUT_LIMITER) + str = ft_strdup((*cur)->next->content.string); + if ((*cur)->content.redir_type == INPUT_LIMITER) + { + if (!set_heredoc_data(*cur, result, data->env)) + return ; + } + else if ((*cur)->content.redir_type == INPUT_FILE) + q4fc(data->create_files, set_redir(&result[0], INPUT_FILE, + format_string(str, data->env, 0), data->env)); + else if ((*cur)->content.redir_type == OUTPUT_OVERRIDE) + q4fc(data->create_files, set_redir(&result[1], OUTPUT_OVERRIDE, + format_string(str, data->env, 0), data->env)); + else if ((*cur)->content.redir_type == OUTPUT_APPEND) + q4fc(data->create_files, set_redir(&result[1], OUTPUT_APPEND, + format_string(str, data->env, 0), data->env)); + i_love_the_norme(cur, tokens); } -static t_token *collect_redir(t_token **tokens, t_redirection *result, - t_token *cur) +static t_redirection *set_redir(t_redirection *redir, int type, char *spec, + t_env *env) { - 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); - } + t_redirection *result; + + redir->type = type; + if (spec != NULL) + redir->specifier = format_string(spec, env, ft_atoi("0")); else + redir->specifier = spec; + if (redir->type != INPUT_LIMITER) { - free_token(cur); - return (NULL); + result = malloc(sizeof(t_redirection)); + if (!result) + return (NULL); + result->type = type; + result->specifier = spec; + return (result); } - return (cur); + return (NULL); } -static void set_redir(t_redirection *redir, int type, char *specifier) +static int set_heredoc_data(t_token *cur, t_redirection *result, t_env *env) { - redir->type = type; - redir->specifier = specifier; -} + char *heredoc_data; -static int is_output_redir(int i) -{ - if (i & (INPUT_FILE | INPUT_LIMITER)) - return (0); - else if (i & (OUTPUT_APPEND | OUTPUT_OVERRIDE)) - return (1); - else + heredoc_data = NULL; + if (cur->content.redir_type == INPUT_LIMITER) { - panic(UNREACHABLE); - return (-1); + heredoc_data = read_heredoc(cur->next->content.string); + if (!heredoc_data) + { + perror("Heredoc allocation failed"); + return (0); + } + set_redir(&result[0], INPUT_LIMITER, heredoc_data, env); } + set_redir(&result[0], INPUT_LIMITER, heredoc_data, env); + return (1); } diff --git a/src/create_files.c b/src/create_files.c new file mode 100644 index 0000000..eee2860 --- /dev/null +++ b/src/create_files.c @@ -0,0 +1,61 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* create_files.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/01/16 16:23:51 by dkaiser #+# #+# */ +/* Updated: 2025/01/20 18:30:40 by dkaiser ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" +#include <sys/fcntl.h> +#include <unistd.h> + +static int cant_write(char *filename); +static void create_file(char *filename, int mode); + +int create_files(t_list *files) +{ + t_redirection *file; + + while (files) + { + if (files->content != NULL) + { + file = (t_redirection *)files->content; + if (file->type == INPUT_FILE && (access(file->specifier, F_OK) == -1 + || access(file->specifier, R_OK) == -1)) + return (EXIT_FAILURE); + if (cant_write(file->specifier)) + break ; + if (file->type == OUTPUT_OVERRIDE) + create_file(file->specifier, O_TRUNC); + else if (file->type == OUTPUT_APPEND) + create_file(file->specifier, O_APPEND); + if (files->next == NULL) + break ; + if (((t_redirection *)files->next->content)->type == 0) + break ; + } + files = files->next; + } + return (EXIT_SUCCESS); +} + +static int cant_write(char *filename) +{ + return (access(filename, F_OK) != -1 && access(filename, W_OK) == -1); +} + +static void create_file(char *filename, int mode) +{ + close(open(filename, O_WRONLY | O_CREAT | mode, 0644)); +} + +void q4fc(t_list **queue, t_redirection *redir) +{ + ft_lstadd_back(queue, ft_lstnew(redir)); +} diff --git a/src/debug_tools.c b/src/debug_tools.c index de59703..6bee1b0 100644 --- a/src/debug_tools.c +++ b/src/debug_tools.c @@ -3,14 +3,16 @@ /* ::: :::::::: */ /* debug_tools.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */ +/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/06/24 15:34:14 by dkaiser #+# #+# */ -/* Updated: 2024/06/28 15:04:43 by dkaiser ### ########.fr */ +/* Updated: 2025/01/20 12:50:36 by chuhlig ### ########.fr */ /* */ /* ************************************************************************** */ #include "debug_tools.h" +#include <stdio.h> +#include <stdarg.h> void dbg(char *msg) { @@ -6,13 +6,12 @@ /* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/10/17 14:31:07 by chuhlig #+# #+# */ -/* Updated: 2024/10/25 19:17:54 by chuhlig ### ########.fr */ +/* Updated: 2025/01/20 19:12:43 by chuhlig ### ########.fr */ /* */ /* ************************************************************************** */ #include "env.h" -#include "get_next_line.h" -#include "libft.h" +#include "minishell.h" #include <stdlib.h> void getenvlst(t_env **env, char **en) @@ -56,9 +55,27 @@ char *env_get(t_env *env, char *name) { while (env != NULL) { - if (!ft_strncmp(env->name, name, ft_strlen(name))) + if (!ft_strncmp(env->name, name, ft_strlen(env->name))) return (env->value); env = env->next; } return (NULL); } + +t_env *env_new(char *name) +{ + t_env *result; + + result = malloc(sizeof(t_env)); + if (!result) + return (NULL); + result->name = name; + return (result); +} + +void free_env_node(t_env *node) +{ + free(node->name); + free(node->value); + free(node); +} diff --git a/src/env_to_strlst.c b/src/env_to_strlst.c index 3a58df9..5806d96 100644 --- a/src/env_to_strlst.c +++ b/src/env_to_strlst.c @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* env_to_strlst.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */ +/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2024/10/21 14:52:08 by dkaiser #+# #+# */ -/* Updated: 2024/10/21 15:07:33 by dkaiser ### ########.fr */ +/* Created: 2024/12/17 19:22:28 by chuhlig #+# #+# */ +/* Updated: 2025/01/18 18:50:49 by chuhlig ### ########.fr */ /* */ /* ************************************************************************** */ @@ -15,20 +15,32 @@ static char *get_var_assign(t_env *cur); -char **env_to_strlst(t_env *env) +static int getsize(t_env *env) { int size; t_env *cur; - char **result; - int i; size = 0; cur = env; - while (cur != NULL) + while (cur) { - size++; + if (!ft_strchr(cur->name, '?')) + size++; cur = cur->next; } + return (size); +} + +char **env_to_strlst(t_env *env) +{ + int size; + t_env *cur; + char **result; + int i; + + size = 0; + cur = env; + size = getsize(env); result = malloc(sizeof(char *) * (size + 1)); if (result == NULL) return (NULL); @@ -36,6 +48,8 @@ char **env_to_strlst(t_env *env) cur = env; while (i < size) { + if (ft_strchr(cur->name, '?')) + cur = cur->next; result[i] = get_var_assign(cur); cur = cur->next; i++; diff --git a/src/env_tools.c b/src/env_tools.c new file mode 100644 index 0000000..25e21ce --- /dev/null +++ b/src/env_tools.c @@ -0,0 +1,21 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* env_tools.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/01/15 16:14:31 by dkaiser #+# #+# */ +/* Updated: 2025/01/15 16:15:10 by dkaiser ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +char **get_split_path(t_env *env) +{ + char *path; + + path = env_get(env, "PATH"); + return (ft_split(path, ':')); +} diff --git a/src/error.c b/src/error.c new file mode 100644 index 0000000..2ca60b2 --- /dev/null +++ b/src/error.c @@ -0,0 +1,30 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* error.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/01/15 16:35:53 by dkaiser #+# #+# */ +/* Updated: 2025/01/20 18:12:40 by dkaiser ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" +#include <errno.h> + +void *error(int err_code, char *err_text, int exit_code, int *ret_code) +{ + errno = err_code; + perror(err_text); + if (ret_code != NULL) + *ret_code = exit_code; + return (NULL); +} + +void command_not_found_error(char *cmd) +{ + ft_printf("%s:", cmd); + ft_putstr_fd(" command not found", 2); + ft_printf("\n"); +} diff --git a/src/execute_cmd.c b/src/execute_cmd.c index 6386fc0..1438f9c 100644 --- a/src/execute_cmd.c +++ b/src/execute_cmd.c @@ -5,72 +5,100 @@ /* +:+ +:+ +:+ */ /* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2024/10/21 13:58:56 by dkaiser #+# #+# */ -/* Updated: 2024/10/25 20:59:22 by chuhlig ### ########.fr */ +/* Created: 2024/12/17 19:21:35 by chuhlig #+# #+# */ +/* Updated: 2025/01/20 20:04:31 by chuhlig ### ########.fr */ /* */ /* ************************************************************************** */ #include "minishell.h" +#include <stdio.h> #include <stdlib.h> -#include <sys/_types/_pid_t.h> -#include <sys/_types/_s_ifmt.h> -#include <sys/fcntl.h> -#include <unistd.h> -#include <fcntl.h> -int execute_cmd(t_cmd *cmd, t_env *env) +static void establish_pipeline(int original_stdin, int original_stdout); +static int exec_cmd(t_cmd *cmd, t_env **env, int original_std[2], int result); + +int is_builtin(char *cmd) { - int result; - char *cmd_path; - int fd; + 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)); +} - cmd_path = get_cmd_path(cmd->args[0], env); - cmd->args[0] = cmd_path; +int execute_builtin(char **args, t_env **env) +{ + if (ft_strcmp(args[0], "export") == 0) + return (export(args, env, ft_atoi("0"))); + 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], "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)); + else if (ft_strcmp(args[0], "exit") == 0) + return (builtin_exit(args, env)); + return (1); +} - if (cmd->redirs[0].type == INPUT_FILE) +int execute_cmd(t_cmd *cmd, t_env **env) +{ + int original_std[2]; + int result; + + original_std[1] = dup(STDOUT_FILENO); + original_std[0] = dup(STDIN_FILENO); + create_files(cmd->create_files); + if (handle_redirections(cmd->redirs) == -1) { - fd = open(cmd->redirs[0].specifier, O_RDONLY); - if (fd < 0) - return (EXIT_FAILURE); - dup2(fd, STDIN_FILENO); + establish_pipeline(original_std[0], original_std[1]); + return (EXIT_FAILURE); } - else if (cmd->redirs[0].type == INPUT_LIMITER) + if (is_builtin(cmd->args[0])) { - dbg("INPUT_LIMITER"); + result = execute_builtin(cmd->args, env); + establish_pipeline(original_std[0], original_std[1]); + return (result); } - if (cmd->redirs[1].type == OUTPUT_APPEND) + return (exec_cmd(cmd, env, original_std, EXIT_SUCCESS)); +} + +static void establish_pipeline(int original_stdin, int original_stdout) +{ + dup2(original_stdout, STDOUT_FILENO); + dup2(original_stdin, STDIN_FILENO); + close(original_stdout); + close(original_stdin); +} + +static int exec_cmd(t_cmd *cmd, t_env **env, int original_std[2], int result) +{ + int i; + int status; + char *cmd_path; + pid_t pid; + + pid = fork(); + if (pid == -1) { - dbg("OUTPUT_APPEND"); - fd = open(cmd->redirs[1].specifier, O_WRONLY | O_CREAT | O_APPEND); - if (fd < 0) - return (EXIT_FAILURE); - dup2(fd, STDOUT_FILENO); + perror("fork"); + establish_pipeline(original_std[0], original_std[1]); + return (EXIT_FAILURE); } - else if (cmd->redirs[1].type == OUTPUT_OVERRIDE) + if (pid == 0) { - fd = open(cmd->redirs[1].specifier, O_WRONLY | O_CREAT | O_TRUNC); - if (fd < 0) - return (EXIT_FAILURE); - dup2(fd, STDOUT_FILENO); - dbg("OUTPUT_OVERRIDE"); + i = 0; + while (cmd->args[i][0] == '\0') + i++; + cmd_path = get_cmd_path(cmd->args[i], *env, &result); + if (cmd_path != NULL) + execve(cmd_path, &(cmd->args[i]), env_to_strlst(*env)); + exit(result); } - result = execve(cmd->args[0], cmd->args, env_to_strlst(env)); - return (result); + waitpid(pid, &status, 0); + establish_pipeline(original_std[0], original_std[1]); + return ((status >> 8) & 255); } - -static int eval_cmd(t_cmd *cmd, t_env **env) -{ - if (ft_strncmp(cmd->args[0], "pwd", 4) == 0) - pwd(*env); - else if (ft_strncmp(cmd->args[0], "echo", 5) == 0) - echo(cmd->args); - else if (ft_strncmp(cmd->args[0], "env", 4) == 0) - ft_env(*env); - else if (ft_strncmp(cmd->args[0], "cd", 3) == 0) - cd(env, cmd->args); - else if (ft_strncmp(cmd->args[0], "unset", 6) == 0) - unset(cmd->args, env); - else if (ft_strncmp(cmd->args[0], "export", 7) == 0) - export(cmd->args, env); - return (0); -}
\ No newline at end of file diff --git a/src/format_string.c b/src/format_string.c new file mode 100644 index 0000000..7e64039 --- /dev/null +++ b/src/format_string.c @@ -0,0 +1,125 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* format_string.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/12/17 19:30:11 by chuhlig #+# #+# */ +/* Updated: 2025/01/19 20:24:05 by chuhlig ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "get_next_line.h" +#include "libft.h" +#include "minishell.h" + +void append_var_exit_code(char **dst, t_env *env) +{ + char *exit_code; + char *result; + + exit_code = env_get(env, "?"); + if (exit_code) + { + result = ft_strjoin(*dst, exit_code); + free(*dst); + *dst = 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 (ft_isalnum(src[*pos + i]) || src[*pos + i] == '_') + i++; + if (i == 0) + return ; + var = ft_substr(src, *pos, i); + value = env_get(env, var); + if (value) + { + result = ft_strjoin(*dst, value); + free(*dst); + *dst = result; + } + *pos += i; + free(var); +} + +static void handle_dollar_sign(char **result, char *str, int *pos, t_env *env) +{ + if (str[*pos + 1] == '?') + { + append_var_exit_code(result, env); + *pos += 2; + } + else if (ft_isalnum(str[*pos + 1]) || str[*pos + 1] == '_') + append_var(result, str, pos, env); + else + { + append_slice(result, str, *pos, *pos + 1); + (*pos)++; + } +} + +char *format_string(char *str, t_env *env, int is_literal) +{ + char *result; + int pos; + int start; + + pos = 0; + start = 0; + result = NULL; + if (!str) + return (NULL); + while (str[pos]) + { + if (str[pos] == '\'' || (str[pos] == '\"' && !is_literal) + || (str[pos] == '$' && !is_literal)) + { + append_slice(&result, str, start, pos); + if (str[pos] == '$') + handle_dollar_sign(&result, str, &pos, env); + else + is_literal ^= (str[pos++] == '\''); + start = pos; + continue ; + } + pos++; + } + return (append_slice(&result, str, start, pos), result); +} diff --git a/src/free_token.c b/src/free_token.c index 9b035ac..512ba23 100644 --- a/src/free_token.c +++ b/src/free_token.c @@ -3,14 +3,15 @@ /* ::: :::::::: */ /* free_token.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */ +/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/06/27 14:38:57 by dkaiser #+# #+# */ -/* Updated: 2024/08/02 14:23:56 by dkaiser ### ########.fr */ +/* Updated: 2025/01/20 12:49:48 by chuhlig ### ########.fr */ /* */ /* ************************************************************************** */ #include "token.h" +#include "debug_tools.h" void free_token(t_token *token) { @@ -19,6 +20,7 @@ void free_token(t_token *token) if (token->next != NULL) token->next->previous = NULL; free(token); + token = NULL; } void free_token_and_connect(t_token *token) @@ -28,6 +30,7 @@ void free_token_and_connect(t_token *token) if (token->next != NULL) token->next->previous = token->previous; free(token); + token = NULL; } void free_tokens(t_token *tokens) diff --git a/src/get_cmd_path.c b/src/get_cmd_path.c index 1ecf393..70043a7 100644 --- a/src/get_cmd_path.c +++ b/src/get_cmd_path.c @@ -3,31 +3,38 @@ /* ::: :::::::: */ /* get_cmd_path.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */ +/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2024/10/17 16:45:47 by dkaiser #+# #+# */ -/* Updated: 2024/10/17 17:11:27 by dkaiser ### ########.fr */ +/* Created: 2024/12/17 19:19:59 by chuhlig #+# #+# */ +/* Updated: 2025/01/20 18:12:33 by dkaiser ### ########.fr */ /* */ /* ************************************************************************** */ #include "libft.h" #include "minishell.h" +#include <errno.h> +#include <sys/errno.h> +#include <sys/stat.h> +#include <sys/unistd.h> +#include <unistd.h> -static char *get_absolute_cmd_path(char *cmd, t_env *env); -static char *find_in_path(char *cmd, t_env *env); +static char *get_simple_cmd_path(char *cmd, int *return_code); +static char *get_absolute_cmd_path(char *cmd, t_env *env, int *return_code); +static char *find_in_path(char *cmd, t_env *env, int *return_code); char **get_split_path(t_env *env); +static int is_directory(char *path); -char *get_cmd_path(char *cmd, t_env *env) +char *get_cmd_path(char *cmd, t_env *env, int *return_code) { if (cmd[0] == '/') - return (ft_strdup(cmd)); + return (get_simple_cmd_path(cmd, return_code)); else if (ft_strchr(cmd, '/')) - return (get_absolute_cmd_path(cmd, env)); + return (get_absolute_cmd_path(cmd, env, return_code)); else - return (find_in_path(cmd, env)); + return (find_in_path(cmd, env, return_code)); } -static char *get_absolute_cmd_path(char *cmd, t_env *env) +static char *get_absolute_cmd_path(char *cmd, t_env *env, int *return_code) { char *cur_dir; char *result; @@ -38,16 +45,23 @@ static char *get_absolute_cmd_path(char *cmd, t_env *env) result = ft_strjoin(cur_dir, cmd); free(cur_dir); if (!result) - return (NULL); + return (error(ENOENT, cmd, 127, return_code)); + if (access(result, F_OK) == -1) + { + free(result); + return (error(ENOENT, cmd, 127, return_code)); + } if (access(result, X_OK) == -1) { free(result); - return (NULL); + return (error(EACCES, cmd, 126, return_code)); } + if (is_directory(cmd)) + return (error(EISDIR, cmd, 126, return_code)); return (result); } -static char *find_in_path(char *cmd, t_env *env) +static char *find_in_path(char *cmd, t_env *env, int *return_code) { char *cur_path; char *cmd_path; @@ -70,13 +84,38 @@ static char *find_in_path(char *cmd, t_env *env) return (cmd_path); path++; } + *return_code = 127; + command_not_found_error(cmd); return (NULL); } -char **get_split_path(t_env *env) +static char *get_simple_cmd_path(char *cmd, int *return_code) +{ + char *result; + + result = ft_strdup(cmd); + if (access(result, F_OK) == -1) + { + free(result); + return (error(ENOENT, cmd, 127, return_code)); + } + else if (access(result, X_OK) == -1) + { + free(result); + return (error(EACCES, cmd, 126, return_code)); + } + if (is_directory(cmd)) + return (error(EISDIR, cmd, 126, return_code)); + return (result); +} + +static int is_directory(char *path) { - char *path; + struct stat path_stat; - path = env_get(env, "PATH"); - return (ft_split(path, ':')); + stat(path, &path_stat); + if ((path_stat.st_mode & S_IFMT) == S_IFDIR) + return (1); + else + return (0); } diff --git a/src/handle_redir.c b/src/handle_redir.c new file mode 100644 index 0000000..e8a1010 --- /dev/null +++ b/src/handle_redir.c @@ -0,0 +1,103 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* handle_redir.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/01/18 18:34:51 by chuhlig #+# #+# */ +/* Updated: 2025/01/20 14:59:38 by chuhlig ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +int handle_input_redirection(t_redirection *redir) +{ + int fd; + + if (redir->type == INPUT_FILE) + { + fd = open_file(redir->specifier, O_RDONLY, 0); + if (fd < 0) + return (-1); + dup2(fd, STDIN_FILENO); + close(fd); + } + else if (redir->type == INPUT_LIMITER) + { + fd = open_file("/tmp/heredoc_tmp", O_WRONLY | O_TRUNC, 0644); + if (fd < 0) + return (-1); + write(fd, redir->specifier, ft_strlen(redir->specifier)); + close(fd); + fd = open_file("/tmp/heredoc_tmp", O_RDONLY, 0); + if (fd < 0) + return (-1); + dup2(fd, STDIN_FILENO); + close(fd); + } + return (0); +} + +int handle_output_redirection(t_redirection *redir) +{ + int fd; + + if (redir->type == OUTPUT_OVERRIDE) + { + fd = open_file(redir->specifier, O_WRONLY | O_TRUNC, 0644); + if (fd < 0) + return (-1); + dup2(fd, STDOUT_FILENO); + close(fd); + } + else if (redir->type == OUTPUT_APPEND) + { + fd = open_file(redir->specifier, O_WRONLY | O_APPEND, 0644); + if (fd < 0) + return (-1); + dup2(fd, STDOUT_FILENO); + close(fd); + } + return (0); +} + +int handle_redirections(t_redirection *redirs) +{ + if (redirs[0].type == INPUT_FILE || redirs[0].type == INPUT_LIMITER) + { + if (handle_input_redirection(&redirs[0]) < 0) + return (-1); + } + if (redirs[1].type == OUTPUT_OVERRIDE || redirs[1].type == OUTPUT_APPEND) + { + if (handle_output_redirection(&redirs[1]) < 0) + return (-1); + } + return (0); +} + +int handle_pipe_parent(int p[2], t_node *node, t_env **env) +{ + int original_stdin; + int result; + + close(p[1]); + original_stdin = dup(STDIN_FILENO); + dup2(p[0], STDIN_FILENO); + result = eval_rec(node->content.pipe.right, env, p[0]); + dup2(original_stdin, STDIN_FILENO); + close(original_stdin); + close(p[0]); + return (result); +} + +int handle_pipe_child(int p[2], t_node *node, t_env **env, int in_fd) +{ + close(p[0]); + dup2(in_fd, STDIN_FILENO); + dup2(p[1], STDOUT_FILENO); + close(p[1]); + exit(eval_rec(node->content.pipe.left, env, in_fd)); +} @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* init.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */ +/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/06/24 15:02:24 by dkaiser #+# #+# */ -/* Updated: 2024/06/24 15:25:57 by dkaiser ### ########.fr */ +/* Updated: 2025/01/13 17:45:46 by chuhlig ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/interpreter.c b/src/interpreter.c index c6a4a00..9cd5292 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -5,86 +5,51 @@ /* +:+ +:+ +:+ */ /* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2024/08/05 13:15:24 by dkaiser #+# #+# */ -/* Updated: 2024/10/25 20:59:16 by chuhlig ### ########.fr */ +/* Created: 2024/12/17 19:15:49 by chuhlig #+# #+# */ +/* Updated: 2025/01/20 20:07:11 by chuhlig ### ########.fr */ /* */ /* ************************************************************************** */ #include "debug_tools.h" #include "minishell.h" -#include <stdlib.h> -#include <sys/_types/_pid_t.h> -#include <sys/cdefs.h> -#include <sys/wait.h> -#include <unistd.h> -static int eval_rec(t_node *node, t_env *env, int in_fd); +int eval_rec(t_node *node, t_env **env, int in_fd); -int eval(t_node *node, t_env *env) +int open_file(char *path, int flags, int mode) { - pid_t pid; - int result; + int fd; - if (node == NULL) - return (EXIT_FAILURE); - result = 0; - pid = fork(); - if (pid < 0) - { - return (EXIT_FAILURE); - } - if (pid == 0) - { - result = eval_rec(node, env, STDIN_FILENO); - exit(result); - } - else - { - waitpid(pid, &result, 0); - } - return (result); + fd = open(path, flags, mode); + if (fd < 0) + perror(path); + return (fd); } -static int eval_rec(t_node *node, t_env *env, int in_fd) +int eval_rec(t_node *node, t_env **env, int in_fd) { + int p[2]; pid_t pid; int result; - int p[2]; - result = pipe(p); - if (result == -1) - return (EXIT_FAILURE); if (node->type == PIPE_NODE) { + if (pipe(p) == -1) + return (perror("pipe"), EXIT_FAILURE); pid = fork(); - if (pid < 0) - { - return (EXIT_FAILURE); - } + if (pid == -1) + return (perror("fork"), close(p[0]), close(p[1]), EXIT_FAILURE); if (pid == 0) - { - close(p[0]); - dup2(in_fd, STDIN_FILENO); - dup2(p[1], STDOUT_FILENO); - result = execute_cmd(&node->content.pipe.left->content.cmd, env); - exit(result); - } - else - { - close(p[1]); - dup2(p[0], STDIN_FILENO); - result = eval_rec(node->content.pipe.right, env, p[0]); - } + handle_pipe_child(p, node, env, in_fd); + result = handle_pipe_parent(p, node, env); } else if (node->type == CMD_NODE) - { result = execute_cmd(&node->content.cmd, env); - } else - { - panic(UNREACHABLE); - return (EXIT_FAILURE); - } + result = EXIT_FAILURE; return (result); } +int eval(t_node *node, t_env **env) +{ + return (eval_rec(node, env, STDIN_FILENO)); +} @@ -6,8 +6,7 @@ /* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/06/22 17:14:03 by dkaiser #+# #+# */ -/* Updated: 2024/08/26 19:55:57 by chuhlig ### ########.fr */ -/* Updated: 2024/10/25 16:06:32 by chuhlig ### ########.fr */ +/* Updated: 2025/01/14 18:41:15 by chuhlig ### ########.fr */ /* */ /* ************************************************************************** */ @@ -15,13 +14,18 @@ int main(int argc, char *argv[], char *envp[]) { - t_env *env; + t_env *env; + static int promptflag; env = NULL; + promptflag = 0; if (!argc && !argv) return (1); if (init()) return (1); getenvlst(&env, envp); - repl("Minishell $ ", &env); + set_return_code(0, &env); + repl("Minishell $ ", &env, &promptflag); + free_envlst(&env); + return (0); } diff --git a/src/new_node.c b/src/new_node.c index c58d291..b2ab7ea 100644 --- a/src/new_node.c +++ b/src/new_node.c @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* new_node.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */ +/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/06/27 11:21:03 by dkaiser #+# #+# */ -/* Updated: 2024/09/17 18:46:35 by dkaiser ### ########.fr */ +/* Updated: 2025/01/20 17:59:01 by dkaiser ### ########.fr */ /* */ /* ************************************************************************** */ @@ -37,7 +37,8 @@ t_node *new_pipe_node(t_node *left, t_node *right) return (node); } -t_node *new_cmd_node(char **args, t_redirection redirs[2]) +t_node *new_cmd_node(char **args, t_redirection redirs[2], + t_list *create_files) { t_node *node; @@ -49,7 +50,9 @@ t_node *new_cmd_node(char **args, t_redirection redirs[2]) { node->content.cmd.redirs[0] = redirs[0]; node->content.cmd.redirs[1] = redirs[1]; + node->content.cmd.create_files = create_files; free(redirs); + redirs = NULL; return (node); } return (NULL); diff --git a/src/new_token.c b/src/new_token.c index 6431c7d..bd65b9d 100644 --- a/src/new_token.c +++ b/src/new_token.c @@ -6,7 +6,7 @@ /* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/06/27 14:29:44 by dkaiser #+# #+# */ -/* Updated: 2024/08/29 15:30:52 by chuhlig ### ########.fr */ +/* Updated: 2025/01/20 19:12:57 by chuhlig ### ########.fr */ /* */ /* ************************************************************************** */ @@ -50,28 +50,3 @@ t_token *new_redir_token(int type, t_token *previous, t_token *next) token->content.redir_type = type; return (token); } - -// void ft_append_token(int type, t_token **list)// but we need somewhere token/node head initialize with nul -// { -// t_token *node; -// t_token *last_node; - -// if (!list) -// return ; -// node = malloc(sizeof(t_token)); -// if (!node) -// return ; -// node->next = NULL; -// node->type = type; -// if (!*list) -// { -// *list = node; -// node->previous = NULL; -// } -// else -// { -// last_node = ft_lstlast(*list); -// last_node->next = node; -// node->previous = last_node; -// } -// }
\ No newline at end of file diff --git a/src/parse_cmd.c b/src/parse_cmd.c index 2755cae..6505384 100644 --- a/src/parse_cmd.c +++ b/src/parse_cmd.c @@ -3,32 +3,42 @@ /* ::: :::::::: */ /* parse_cmd.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */ +/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/07/08 15:06:25 by dkaiser #+# #+# */ -/* Updated: 2024/08/11 12:20:06 by dkaiser ### ########.fr */ +/* Updated: 2025/01/20 19:09:21 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; + t_list *create_files; - redirs = collect_redirs(&tokens); - args = collect_args(&tokens); - return (new_cmd_node(args, redirs)); + create_files = NULL; + redirs = collect_redirs(&tokens, *env, &create_files); + if (redirs == NULL) + return (NULL); + args = collect_args(&tokens, env); + if (args == NULL) + { + free(redirs); + return (NULL); + } + return (new_cmd_node(args, redirs, create_files)); } -static char **collect_args(t_token **tokens) +static char **collect_args(t_token **tokens, t_env **env) { t_token *cur; char **result; int i; + t_token *next; cur = *tokens; i = 0; @@ -41,11 +51,12 @@ static char **collect_args(t_token **tokens) i = 0; while (cur != NULL && cur->type == STRING_TOKEN) { + next = cur->next; if (cur->previous) free_token(cur->previous); - result[i] = cur->content.string; + result[i] = format_string(cur->content.string, *env, ft_atoi("0")); i++; - cur = cur->next; + cur = next; } result[i] = NULL; return (result); diff --git a/src/parser.c b/src/parser.c index 06c1df7..13ab10d 100644 --- a/src/parser.c +++ b/src/parser.c @@ -3,35 +3,36 @@ /* ::: :::::::: */ /* parser.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */ +/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/06/29 15:53:29 by dkaiser #+# #+# */ -/* Updated: 2024/09/17 19:03:48 by dkaiser ### ########.fr */ +/* Updated: 2025/01/20 19:13:31 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; @@ -39,16 +40,17 @@ static t_node *parse_statement(t_token *tokens) if (left_side_tokens == NULL) { free_tokens(tokens); + tokens = NULL; return (NULL); } 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)); } } @@ -69,6 +71,7 @@ t_token *split_at_first(t_token **tokens, int type) if (result == split) result = NULL; free_token(split); + split = NULL; return (result); } diff --git a/src/praise_the_norme.c b/src/praise_the_norme.c new file mode 100644 index 0000000..a22843b --- /dev/null +++ b/src/praise_the_norme.c @@ -0,0 +1,30 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* praise_the_norme.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/01/20 18:35:41 by dkaiser #+# #+# */ +/* Updated: 2025/01/20 18:39:31 by dkaiser ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +void i_love_the_norme(t_token **cur, t_token **tokens) +{ + t_token *next_token; + + next_token = (*cur)->next; + free_token_and_connect(*cur); + if (next_token) + { + if (next_token->previous == NULL) + *tokens = next_token->next; + *cur = next_token->next; + free_token_and_connect(next_token); + } + else + *cur = NULL; +} diff --git a/src/read_heredoc.c b/src/read_heredoc.c new file mode 100644 index 0000000..53633e8 --- /dev/null +++ b/src/read_heredoc.c @@ -0,0 +1,76 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* read_heredoc.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/01/15 18:22:09 by dkaiser #+# #+# */ +/* Updated: 2025/01/15 19:08:07 by dkaiser ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" +#include <errno.h> +#include <stdio.h> +#include <sys/errno.h> + +static char *concat_str(char *temp, char *line); +static char *get_result(char *temp, char *result, char *line); +static void *print_error_and_free(char *result); + +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) + return (print_error_and_free(result)); + result = get_result(temp, result, line); + total_length += line_length; + } + return (result); +} + +static char *concat_str(char *temp, char *line) +{ + ft_strcat(temp, line); + ft_strcat(temp, "\n"); + free(line); + return (temp); +} + +static char *get_result(char *temp, char *result, char *line) +{ + if (result) + { + ft_strcpy(temp, result); + free(result); + } + else + temp[0] = '\0'; + return (concat_str(temp, line)); +} + +static void *print_error_and_free(char *result) +{ + errno = ENOMEM; + perror("heredoc"); + free(result); + return (NULL); +} @@ -6,35 +6,38 @@ /* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/06/24 16:07:04 by dkaiser #+# #+# */ -/* Updated: 2024/10/22 17:05:14 by chuhlig ### ########.fr */ +/* Updated: 2025/01/20 17:58:43 by dkaiser ### ########.fr */ /* */ /* ************************************************************************** */ #include "../include/minishell.h" #include "token.h" -void repl(const char *prompt, t_env **env) +void repl(const char *prompt, t_env **env, int *promptflag) { char *input; t_token *token_list; t_list *lines; + (*promptflag)++; while (1) { input = readline(prompt); if (input == NULL) - return ; + { + if (*promptflag > 1) + (*promptflag)--; + printf("exit\n"); + break ; + } if (input[0] == '\0') continue ; add_history(input); token_list = NULL; tokenizer(input, &token_list, '\0'); - lines = parse(token_list); + lines = parse(token_list, env); if (lines) - { - print_ast(lines->content); - eval(lines->content, env); - } + set_return_code(eval(lines->content, env), env); free(input); } } diff --git a/src/signal_handling.c b/src/signal_handling.c index a19fa94..6c6ca1e 100644 --- a/src/signal_handling.c +++ b/src/signal_handling.c @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* signal_handling.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */ +/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/06/24 15:08:43 by dkaiser #+# #+# */ -/* Updated: 2024/06/25 13:33:26 by dkaiser ### ########.fr */ +/* Updated: 2025/01/20 12:15:32 by chuhlig ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/tokenizer.c b/src/tokenizer.c index d7a96f7..e202de6 100644 --- a/src/tokenizer.c +++ b/src/tokenizer.c @@ -13,6 +13,26 @@ #include "minishell.h" #include "token.h" +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 print_token(t_token *token) { if (DEBUG) @@ -77,11 +97,11 @@ void handle_special_chars(char *s, int *i, int *start, t_token **token_list) *token_list = new_token(PIPE_TOKEN, *token_list, NULL); else if (s[*i] == '\n') *token_list = new_token(NEWLINE_TOKEN, *token_list, NULL); - print_token(*token_list); if (s[*i] == '<' && s[*i + 1] == '<') (*i)++; if (s[*i] == '>' && s[*i + 1] == '>') (*i)++; + print_token(*token_list); *start = *i + 1; } @@ -111,6 +131,5 @@ void tokenizer(char *s, t_token **token_list, char quote_check) pos = i + 1; } } - while ((*token_list)->previous) - *token_list = (*token_list)->previous; + *token_list = reverse_token_list(*token_list); } |
