diff --git a/README.md b/README.md index 249e0c5..bb574cb 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,16 @@ A lot of amazing shell stuff - libreadline-dev - libncurses-dev +## Comments on work +- Checked if path is a directory and send appropriate message +- `executor_absolute_path` => extracted some code into helpers to make it norminette compliant +- `executor_child` => refactored putstr_fd into error_msg | checked if file on path is exectuable to show permission denied where applicable +- `lexer_token_next` => extracted code for norminette +- `parser` => **A LOT** of work in all files for norminette compliancy +- `expander_parse_string` => Fixed so that $HOME/test.txt returns the correct path and file + ## Edge Cases -- `cat $PWD/test` should expand, +- `cat $PWD/test` should expand, - `cd -` : `bash: cd: OLDPWD not set` - `cd ~` : does not expand ? diff --git a/inc/allowed.h b/inc/allowed.h index e562c19..7b2859f 100644 --- a/inc/allowed.h +++ b/inc/allowed.h @@ -6,7 +6,7 @@ /* By: qmennen +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/02/04 16:13:11 by whaffman #+# #+# */ -/* Updated: 2025/02/06 16:14:44 by qmennen ### ########.fr */ +/* Updated: 2025/02/27 16:36:39 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ @@ -26,6 +26,7 @@ # include # include # include +# include # include # include diff --git a/inc/parser.h b/inc/parser.h index c07368f..a3d0483 100644 --- a/inc/parser.h +++ b/inc/parser.h @@ -1,23 +1,25 @@ -/* ************************************************************************** */ -/* */ -/* :::::::: */ -/* parser.h :+: :+: */ -/* +:+ */ -/* By: qmennen +#+ */ -/* +#+ */ -/* Created: 2025/02/11 14:03:03 by qmennen #+# #+# */ -/* Updated: 2025/02/11 17:19:01 by whaffman ######## odam.nl */ -/* */ -/* ************************************************************************** */ - -#ifndef PARSER_H -# define PARSER_H - -# include "minishell.h" - -t_command *parser_command_new(t_minishell *msh, char *cmd); -char **parser_get_arguments(t_list *list, t_minishell *msh); -t_list *parser_get_commands(t_minishell *msh); -t_list *parser_get_input_redirects(t_list *list); - -#endif +/* ************************************************************************** */ +/* */ +/* :::::::: */ +/* parser.h :+: :+: */ +/* +:+ */ +/* By: qmennen +#+ */ +/* +#+ */ +/* Created: 2025/02/11 14:03:03 by qmennen #+# #+# */ +/* Updated: 2025/02/11 17:19:01 by whaffman ######## odam.nl */ +/* */ +/* ************************************************************************** */ + +#ifndef PARSER_H +# define PARSER_H + +# include "minishell.h" + +t_command *parser_alloc_command(t_minishell *msh, char *cmd); +t_list *parser_get_commands(t_minishell *msh); +t_list *parser_get_input_redirects(t_list *list); +void parser_create_command(t_minishell *msh, t_command *cmd, t_list **l_tkn); +char **parser_get_arguments(t_list *list, t_minishell *msh); +int parser_validate_command(t_command *command); + +#endif diff --git a/inc/redirect.h b/inc/redirect.h index 2da3c94..3a1e568 100644 --- a/inc/redirect.h +++ b/inc/redirect.h @@ -1,27 +1,27 @@ -/* ************************************************************************** */ -/* */ -/* :::::::: */ -/* redirect.h :+: :+: */ -/* +:+ */ -/* By: Quinten +#+ */ -/* +#+ */ -/* Created: 2025/02/23 12:26:29 by Quinten #+# #+# */ -/* Updated: 2025/02/23 12:26:29 by Quinten ######## odam.nl */ -/* */ -/* ************************************************************************** */ - -#ifndef REDIRECT_H -# define REDIRECT_H -# include "minishell.h" - -t_redirect *redirect_new(t_minishell *msh, t_token_type type, char *value); -void redirect_new_error(t_minishell *msh, t_list **redirects); -void redirect_create(t_minishell *msh, t_list **tokens, t_list **redirects, t_token_type type); -t_list *redirect_get_inputs(t_minishell *msh, t_list *list); -t_list *redirect_get_outputs(t_minishell *msh, t_list *list); -int redirect_is_valid(t_list *lst, t_token *token, int mode); -int redirect_token_type(t_token *token); -int redirect_is_delimiter(t_token *token); -int process_heredoc(t_minishell *msh, t_token *heredoc, t_token *delim); - -#endif +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* redirect.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/02/23 12:26:29 by Quinten #+# #+# */ +/* Updated: 2025/02/27 18:09:47 by qmennen ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef REDIRECT_H +# define REDIRECT_H +# include "minishell.h" + +t_redirect *redirect_new(t_minishell *msh, t_token_type type, char *value); +void redirect_new_error(t_minishell *msh, t_list **redirects, int flag); +int redirect_create(t_minishell *msh, t_list **tokens, t_list **redirects, t_token_type type); +t_list *redirect_get_inputs(t_minishell *msh, t_list *list); +t_list *redirect_get_outputs(t_minishell *msh, t_list *list); +int redirect_is_valid(t_list *lst, t_token *token, int mode); +int redirect_token_type(t_token *token); +int redirect_is_delimiter(t_token *token); +int process_heredoc(t_minishell *msh, t_token *heredoc, t_token *delim); + +#endif diff --git a/inc/tokenizer.h b/inc/tokenizer.h index cfd415e..bab22bf 100644 --- a/inc/tokenizer.h +++ b/inc/tokenizer.h @@ -1,12 +1,12 @@ /* ************************************************************************** */ /* */ -/* :::::::: */ -/* tokenizer.h :+: :+: */ -/* +:+ */ -/* By: qmennen +#+ */ -/* +#+ */ -/* Created: 2025/02/05 12:36:00 by whaffman #+# #+# */ -/* Updated: 2025/02/26 15:45:26 by whaffman ######## odam.nl */ +/* ::: :::::::: */ +/* tokenizer.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/02/05 12:36:00 by whaffman #+# #+# */ +/* Updated: 2025/02/27 19:03:09 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ @@ -21,13 +21,16 @@ void ft_lexer_free(t_minishell *msh, t_lexer *lexer); void lexer_readchar(t_lexer *lexer); char *lexer_readword(t_minishell *msh, t_lexer *lexer); t_list *ft_parse_input(t_minishell *msh); +char *lexer_parse_quotes(t_minishell *msh, t_lexer *lexer); /** * Token */ -t_token *ft_token_next(t_minishell *msh, t_lexer *lexer); -t_token *token_new(t_minishell *msh, t_token_type type, char *c, int pos); -void ft_token_free(t_minishell *msh, t_token *token); -void ft_clear_tokenlist(t_minishell *msh, void *content); -t_token *token_parse(t_minishell *msh, t_lexer *lexer); +t_token *ft_token_next(t_minishell *msh, t_lexer *lexer); +t_token *token_new(t_minishell *msh, t_token_type type, char *c, int pos); +void ft_token_free(t_minishell *msh, t_token *token); +void ft_clear_tokenlist(t_minishell *msh, void *content); +t_token *token_parse(t_minishell *msh, t_lexer *lexer); +char *token_type_convert(t_token_type type); +t_token_type token_char_convert(char c, int is_double); #endif // TOKENIZER_H diff --git a/sources.mk b/sources.mk new file mode 100644 index 0000000..e85d1ea --- /dev/null +++ b/sources.mk @@ -0,0 +1,24 @@ +VPATH = src:src/prompt:src/utils:src/lexer:src/token:src/environment:src/executor:src/parser:src/debug:src/expander:src/builtin:src/signal:src/redirect: +SOURCES = history_load.c history_write.c prompt.c print_banner.c check_malloc.c \ +free_command_list.c free_freelist.c free_lexer.c free_minishell.c \ +free_safe.c free_token.c free_token_list.c ft_lstclear_safe.c \ +ft_lstnew_safe.c ft_strdup_safe.c ft_strjoin_safe.c malloc_safe.c \ +error_msg.c free_minishell_line.c ft_substr_safe.c init_minishell.c \ +lexer_read_char.c lexer_new.c lexer_parse_input.c lexer_read_word.c \ +lexer_token_next.c token_new.c token_parse.c environment_add.c \ +environment_del.c environment_free.c environment_free_list.c \ +environment_get.c environment_get_arr.c environment_parse.c \ +environment_print.c executor_close_fds.c executor_absolute_path.c \ +executor_count_fds.c executor_create_pipes.c \ +executor_create_redirects.c executor_open_fds.c \ +executor_execute_pipeline.c executor_fork.c executor_child.c \ +parser_create_command.c parser_get_arguments.c parser_alloc_command.c \ +parser_get_commands.c parser_validate_command.c print_commands.c \ +print_freelist.c expander_is_character.c expander_expand_dollar.c \ +expander_allocate_memory.c expander_get_variable.c \ +expander_parse_variables.c expander_parse_string.c is_builtin.c \ +simple_builtins.c builtin_cd.c builtin_echo.c builtin_env.c \ +builtin_exit.c builtin_export.c builtin_pwd.c builtin_router.c \ +builtin_unset.c signal.c signal_init.c.c redirect_get_inputs.c \ +redirect_get_outputs.c redirect_new.c redirect_new_error.c \ +redirect_process_heredoc.c redirect_valid_type.c main.c \ diff --git a/src/builtin/builtin_export.c b/src/builtin/builtin_export.c index 8b1120b..74714c7 100644 --- a/src/builtin/builtin_export.c +++ b/src/builtin/builtin_export.c @@ -18,8 +18,8 @@ int builtin_export(t_minishell *msh, t_command *cmd) char **arr; int i; - i = 1; - while (cmd->args[i] != NULL) + i = 0; + while (cmd->args[++i] != NULL) { arr = ft_split(cmd->args[i], '='); if (arr[1] == NULL) @@ -37,7 +37,6 @@ int builtin_export(t_minishell *msh, t_command *cmd) else environment_add(msh, arr[0], arr[1]); ft_free_arr(arr); - i++; } return (SUCCESS); } diff --git a/src/executor/executor_absolute_path.c b/src/executor/executor_absolute_path.c index a193c46..a876e87 100644 --- a/src/executor/executor_absolute_path.c +++ b/src/executor/executor_absolute_path.c @@ -12,6 +12,34 @@ #include "minishell.h" +static char *resolve_relative(t_minishell *msh, char *cmd) +{ + char *executable; + + if (access(cmd, F_OK) == 0) + { + executable = ft_strdup_safe(msh, cmd); + if (!executable) + return (NULL); + return (executable); + } + return (NULL); +} + +static char *resolve_path(t_minishell *msh, char *path, char *cmd) +{ + char *executable; + + executable = malloc_safe(msh, ft_strlen(path) + ft_strlen(cmd) + 2); + ft_strlcpy(executable, path, ft_strlen(path) + 1); + ft_strlcat(executable, "/", ft_strlen(path) + 2); + ft_strlcat(executable, cmd, ft_strlen(path) + ft_strlen(cmd) + 2); + if (access(executable, F_OK) == 0) + return (executable); + free_safe(msh, (void **)&executable); + return (NULL); +} + char *executor_absolute_path(t_minishell *msh, char *cmd) { char **path; @@ -20,16 +48,7 @@ char *executor_absolute_path(t_minishell *msh, char *cmd) int i; if (cmd[0] == '/' || cmd[0] == '.') - { - if (access(cmd, F_OK) == 0) - { - executable = ft_strdup_safe(msh, cmd); - if (!executable) - return (NULL); - return (executable); - } - return (NULL); - } + return (resolve_relative(msh, cmd)); path_env = environment_get(msh, "PATH"); if (!path_env) return (NULL); @@ -37,16 +56,9 @@ char *executor_absolute_path(t_minishell *msh, char *cmd) i = 0; while (path[i] != NULL) { - executable = malloc_safe(msh, ft_strlen(path[i]) + ft_strlen(cmd) + 2); - ft_strlcpy(executable, path[i], ft_strlen(path[i]) + 1); - ft_strlcat(executable, "/", ft_strlen(path[i]) + 2); - ft_strlcat(executable, cmd, ft_strlen(path[i]) + ft_strlen(cmd) + 2); - if (access(executable, F_OK) == 0) - { - ft_free_arr(path); + executable = resolve_path(msh, path[i], cmd); + if (executable) return (executable); - } - free_safe(msh, (void **)&executable); i++; } return (ft_free_arr(path), NULL); diff --git a/src/executor/executor_child.c b/src/executor/executor_child.c index 904bedd..1e64f47 100644 --- a/src/executor/executor_child.c +++ b/src/executor/executor_child.c @@ -6,12 +6,24 @@ /* By: qmennen +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/02/12 21:25:10 by willem #+# #+# */ -/* Updated: 2025/02/26 18:20:34 by qmennen ### ########.fr */ +/* Updated: 2025/02/27 18:12:48 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ #include "minishell.h" +static int is_dir(char *path) +{ + struct stat path_stats; + + if (stat(path, &path_stats) < 0) + { + error_msg("is_dir", "path could not be read"); + return (0); + } + return (S_ISDIR(path_stats.st_mode)); +} + void executor_child(t_minishell *msh, t_command *command) { char *path; @@ -22,12 +34,17 @@ void executor_child(t_minishell *msh, t_command *command) dup2(command->fd_out, 1); executor_close_fds(command->n_fds); path = executor_absolute_path(msh, command->args[0]); - if (path == NULL) + if (path == NULL || access(path, F_OK | X_OK) != 0) + { + error_msg("minishell", "command not found"); + return ; + } + if (is_dir(path)) { ft_putstr_fd(RED BOLD, 2); + ft_putstr_fd("minishell: ", 2); ft_putstr_fd(command->args[0], 2); - ft_putstr_fd(": " RESET "command not found\n", 2); - return ; + ft_putstr_fd(": " RESET "Is a directory\n", 2); } execve(path, command->args, environment_get_arr(msh)); } diff --git a/src/expander/expander_parse_string.c b/src/expander/expander_parse_string.c index 1241ac0..1b2d213 100644 --- a/src/expander/expander_parse_string.c +++ b/src/expander/expander_parse_string.c @@ -40,9 +40,9 @@ char *expander_parse_string(char *s, t_minishell *msh) current = variables; i = 0; j = 0; - while (s[i] && current) + while (s[i]) { - if (s[i] == '$' && s[i + 1]) + if (s[i] == '$' && s[i + 1] && current) { i++; i += expander_expand_dollar(s + i, string, &j, current); diff --git a/src/lexer/lexer_parse_quotes.c b/src/lexer/lexer_parse_quotes.c new file mode 100644 index 0000000..09010f9 --- /dev/null +++ b/src/lexer/lexer_parse_quotes.c @@ -0,0 +1,39 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* lexer_parse_quotes.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/02/27 19:02:37 by qmennen #+# #+# */ +/* Updated: 2025/02/27 19:26:35 by qmennen ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +char *lexer_parse_quotes(t_minishell *msh, t_lexer *lexer) +{ + int start; + int len; + char qc; + char *word; + + qc = lexer->current_char; + word = NULL; + lexer_readchar(lexer); + start = lexer->pos; + while (lexer->current_char != '\0' && lexer->current_char != qc) + lexer_readchar(lexer); + len = lexer->pos - start; + word = malloc_safe(msh, sizeof(char) * len + 1); + ft_strlcpy(word, lexer->input + start, len + 1); + if (lexer->current_char == qc) + lexer_readchar(lexer); + else + { + free_safe(msh, (void **)&word); + return (NULL); + } + return (word); +} diff --git a/src/lexer/lexer_read_word.c b/src/lexer/lexer_read_word.c index 78c50f4..bb12c8d 100644 --- a/src/lexer/lexer_read_word.c +++ b/src/lexer/lexer_read_word.c @@ -1,41 +1,55 @@ /* ************************************************************************** */ /* */ -/* :::::::: */ -/* lexer_read_word.c :+: :+: */ -/* +:+ */ -/* By: qmennen +#+ */ -/* +#+ */ -/* Created: 2025/02/05 19:03:47 by qmennen #+# #+# */ -/* Updated: 2025/02/26 16:13:59 by whaffman ######## odam.nl */ +/* ::: :::::::: */ +/* lexer_read_word.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/02/05 19:03:47 by qmennen #+# #+# */ +/* Updated: 2025/02/27 19:30:09 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ #include "minishell.h" -static char *parse_quotes(t_minishell *msh, t_lexer *lexer) +static int match_quotes(t_minishell *msh, t_lexer *lexer) { - int start; - int len; - char qc; - char *word; + char c; + int i; + int d_qts; + int s_qts; - qc = lexer->current_char; - word = NULL; - lexer_readchar(lexer); - start = lexer->pos; - while (lexer->current_char != '\0' && lexer->current_char != qc) - lexer_readchar(lexer); - len = lexer->pos - start; - word = malloc_safe(msh, sizeof(char) * len + 1); - ft_strlcpy(word, lexer->input + start, len + 1); - if (lexer->current_char == qc) - lexer_readchar(lexer); - else + i = lexer->pos; + c = lexer->input[i]; + d_qts = 0; + s_qts = 0; + //TODO: Normalize this validation. Happens a lot + while (ft_isprint(c) && c != '<' && c != '>' && c != '|' && c != '\0' && !ft_isspace(c)) { - free_safe(msh, (void **)&word); - return (NULL); + if (lexer->input[i] == '\'') + s_qts++; + if (lexer->input[i] == '\'') + d_qts++; + i++; + c = lexer->input[i]; } - return (word); + return ((s_qts % 2) == 0 && (d_qts % 2) == 0); +} + +static int calculate_word_len(t_minishell *msh, t_lexer *lexer) +{ + int i; + int len; + + len = 1; + i = lexer->pos; + while (ft_isprint(lexer->input[i]) && lexer->input[i] != '<' && lexer->input[i]!= '>' && lexer->input[i] != '|' && lexer->input[i] != '\0' && !ft_isspace(lexer->input[i])) + { + if(lexer->input[i] != '\'' && lexer->input[i] != '"') + len++; + i++; + } + return (len); } char *lexer_readword(t_minishell *msh, t_lexer *lexer) @@ -43,21 +57,28 @@ char *lexer_readword(t_minishell *msh, t_lexer *lexer) int start; int len; char *word; + char c; start = lexer->pos; + if (lexer->current_char == '"' || lexer->current_char == '\'') { - return (parse_quotes(msh, lexer)); + return (lexer_parse_quotes(msh, lexer)); + } - while (ft_isprint(lexer->current_char) && lexer->current_char != '<' - && lexer->current_char != '>' && lexer->current_char != '|' - && lexer->current_char != '\0' && !ft_isspace(lexer->current_char) - && lexer->current_char != '"' && lexer->current_char != '\'') + if (!match_quotes(msh, lexer)) + return (NULL); + len = calculate_word_len(msh, lexer); + word = malloc_safe(msh, sizeof(char) * len); + c = lexer->current_char; + len = 0; + while (ft_isprint(c) && c != '<' && c != '>' && c != '|' && c != '\0' && !ft_isspace(c)) { + if(c != '\'' && c != '"') + word[len++] = lexer->current_char; lexer_readchar(lexer); + c = lexer->current_char; } - len = lexer->pos - start; - word = malloc_safe(msh, sizeof(char) * len + 1); - ft_strlcpy(word, lexer->input + start, len + 1); + word[len] = 0; return (word); } diff --git a/src/lexer/lexer_token_next.c b/src/lexer/lexer_token_next.c index d3c1181..12d571c 100644 --- a/src/lexer/lexer_token_next.c +++ b/src/lexer/lexer_token_next.c @@ -11,7 +11,6 @@ /* ************************************************************************** */ #include "minishell.h" -#include "typedef.h" static t_token_type get_word_type(char c) { @@ -23,6 +22,21 @@ static t_token_type get_word_type(char c) return (T_WORD); } +static t_token *process_word(t_minishell *msh, t_lexer *lexer, int pos) +{ + t_token_type word_type; + t_token *token; + char *word; + + word_type = get_word_type(lexer->current_char); + word = lexer_readword(msh, lexer); + if (!word) + return (token_new(msh, T_ERROR, &(lexer->current_char), pos)); + token = token_new(msh, word_type, word, pos); + free_safe(msh, (void **)&word); + return (token); +} + /** * @brief Retrieves the next token from the lexer. * @@ -45,32 +59,23 @@ static t_token_type get_word_type(char c) t_token *ft_token_next(t_minishell *msh, t_lexer *lexer) { t_token *token; - t_token_type word_type; - char *word; int current_pos; + char c; token = NULL; while (ft_isspace(lexer->current_char)) lexer_readchar(lexer); current_pos = lexer->pos; - if (lexer->current_char == '\0') + c = lexer->current_char; + if (c == '\0') token = token_new(msh, T_EOF, NULL, current_pos); - else if (lexer->current_char == '<' || lexer->current_char == '>' - || lexer->current_char == '|') + else if (c == '<' || c == '>' + || c == '|') token = token_parse(msh, lexer); else if (ft_isprint(lexer->current_char)) - { - word_type = get_word_type(lexer->current_char); - word = lexer_readword(msh, lexer); - if (!word) - return (token_new(msh, T_ERROR, &lexer->current_char, current_pos)); - token = token_new(msh, word_type, word, current_pos); - free_safe(msh, (void **)&word); - } + token = process_word(msh, lexer, current_pos); else - { token = token_new(msh, T_ERROR, NULL, current_pos); - printf("token->type: %d\n", token->type); - } + c = lexer->current_char; return (token); } diff --git a/src/parser/parser_new_command.c b/src/parser/parser_alloc_command.c similarity index 95% rename from src/parser/parser_new_command.c rename to src/parser/parser_alloc_command.c index 3599cba..fc49925 100644 --- a/src/parser/parser_new_command.c +++ b/src/parser/parser_alloc_command.c @@ -12,7 +12,7 @@ #include "minishell.h" -t_command *parser_command_new(t_minishell *msh, char *cmd) +t_command *parser_alloc_command(t_minishell *msh, char *cmd) { t_command *command; diff --git a/src/parser/parser_create_command.c b/src/parser/parser_create_command.c new file mode 100644 index 0000000..723f860 --- /dev/null +++ b/src/parser/parser_create_command.c @@ -0,0 +1,20 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* parser_create_command.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/02/27 13:35:02 by qmennen #+# #+# */ +/* Updated: 2025/02/27 13:36:48 by qmennen ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +void parser_create_command(t_minishell *msh, t_command *cmd, t_list **l_tkn) +{ + cmd->args = parser_get_arguments(*l_tkn, msh); + cmd->redirect_in = redirect_get_inputs(msh, *l_tkn); + cmd->redirect_out = redirect_get_outputs(msh, *l_tkn); +} diff --git a/src/parser/parser_get_arguments.c b/src/parser/parser_get_arguments.c index b0f2033..1ce6230 100644 --- a/src/parser/parser_get_arguments.c +++ b/src/parser/parser_get_arguments.c @@ -6,7 +6,7 @@ /* By: qmennen +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/02/11 16:20:09 by qmennen #+# #+# */ -/* Updated: 2025/02/26 18:35:27 by qmennen ### ########.fr */ +/* Updated: 2025/02/27 18:58:48 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ @@ -34,13 +34,23 @@ static int count_cmds(t_list *list) static int parser_should_expand(t_list *value) { t_token *token; + int i; token = (t_token *)value->content; if (!token) return (0); - return ((token->type == T_DQWORD && ft_strchr(token->value, '$')) - || (token->type == T_WORD - && token->value[0] == '$' + i = 0; + if (token->type == T_DQWORD) + { + while (token->value[i]) + { + if (token->value[i] == '$' && !expander_character_valid(token->value[i + 1])) + return (0); + i++; + } + return (1); + } + return ((token->type == T_WORD && token->value[0] == '$' && token->value[1])); } diff --git a/src/parser/parser_get_commands.c b/src/parser/parser_get_commands.c index 44e182f..31ec57d 100644 --- a/src/parser/parser_get_commands.c +++ b/src/parser/parser_get_commands.c @@ -6,32 +6,17 @@ /* By: qmennen +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/02/11 14:06:02 by qmennen #+# #+# */ -/* Updated: 2025/02/18 20:36:01 by qmennen ### ########.fr */ +/* Updated: 2025/02/27 16:07:54 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ #include "minishell.h" -#include "utils.h" -static int is_command_token(t_token *token) +static int is_command_token(t_token *token) { return (token->type < 3 || redirect_token_type(token)); } -static int validate_redirects(t_list *lst) -{ - t_list *token; - - token = lst; - while (token) - { - if (((t_redirect *)token->content)->type == T_ERROR) - return (0); - token = token->next; - } - return (1); -} - t_list *parser_get_commands(t_minishell *msh) { t_list *command_list; @@ -46,14 +31,10 @@ t_list *parser_get_commands(t_minishell *msh) while (current) { token = (t_token *) current->content; - command = parser_command_new(msh, ft_strdup_safe(msh, token->value)); - command->args = parser_get_arguments(current, msh); - command->redirect_in = redirect_get_inputs(msh, current); - command->redirect_out = redirect_get_outputs(msh, current); - if (!validate_redirects(command->redirect_in)) - { + command = parser_alloc_command(msh, ft_strdup_safe(msh, token->value)); + parser_create_command(msh, command, ¤t); + if (! parser_validate_command(command)) break ; - } ft_lstadd_back(&command_list, ft_lstnew_safe(msh, command)); while (current && is_command_token((t_token *)current->content)) current = current->next; diff --git a/src/parser/parser_validate_command.c b/src/parser/parser_validate_command.c new file mode 100644 index 0000000..e15e38d --- /dev/null +++ b/src/parser/parser_validate_command.c @@ -0,0 +1,37 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* parser_validate_command.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/02/27 16:06:33 by qmennen #+# #+# */ +/* Updated: 2025/02/27 16:08:49 by qmennen ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +static int validate_redirects(t_list *lst) +{ + t_list *token; + + token = lst; + while (token) + { + if (((t_redirect *)token->content)->type == T_ERROR) + return (0); + token = token->next; + } + return (1); +} + +int parser_validate_command(t_command *command) +{ + int r_in; + int r_out; + + r_in = validate_redirects(command->redirect_in); + r_out = validate_redirects(command->redirect_out); + return (r_in && r_out); +} diff --git a/src/redirect/redirect_get_inputs.c b/src/redirect/redirect_get_inputs.c index 2eaabd3..75d0a10 100644 --- a/src/redirect/redirect_get_inputs.c +++ b/src/redirect/redirect_get_inputs.c @@ -6,7 +6,7 @@ /* By: qmennen +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/02/23 12:29:05 by Quinten #+# #+# */ -/* Updated: 2025/02/26 17:38:59 by qmennen ### ########.fr */ +/* Updated: 2025/02/27 18:09:15 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ @@ -39,10 +39,9 @@ t_list *redirect_get_inputs(t_minishell *msh, t_list *list) } check_heredoc(msh, current, token); flag = redirect_is_valid(current, token, F_OK | R_OK); - redirect_create(msh, ¤t, &redirects, token->type); + flag && (redirect_create(msh, ¤t, &redirects, token->type)); current = current->next; } - if (flag <= 0) - redirect_new_error(msh, &redirects); + redirect_new_error(msh, &redirects, flag); return (redirects); } diff --git a/src/redirect/redirect_get_outputs.c b/src/redirect/redirect_get_outputs.c index 19a4a4e..0ad2f2d 100644 --- a/src/redirect/redirect_get_outputs.c +++ b/src/redirect/redirect_get_outputs.c @@ -1,41 +1,40 @@ -/* ************************************************************************** */ -/* */ -/* :::::::: */ -/* redirect_get_outputs.c :+: :+: */ -/* +:+ */ -/* By: Quinten +#+ */ -/* +#+ */ -/* Created: 2025/02/23 12:37:24 by Quinten #+# #+# */ -/* Updated: 2025/02/23 12:37:24 by Quinten ######## odam.nl */ -/* */ -/* ************************************************************************** */ - -#include "minishell.h" - -t_list *redirect_get_outputs(t_minishell *msh, t_list *list) -{ - t_list *current; - t_list *redirects; - t_token *token; - int flag; - - flag = 1; - redirects = NULL; - current = list; - token = (t_token *)current->content; - while (current && flag && !redirect_is_delimiter(token)) - { - token = (t_token *)current->content; - if (token->type != T_REDIRECT_OUT && token->type != T_APPEND_OUT) - { - current = current->next; - continue ; - } - flag = redirect_is_valid(current, token, -1); - redirect_create(msh, ¤t, &redirects, token->type); - current = current->next; - } - if (flag <= 0) - redirect_new_error(msh, &redirects); - return (redirects); -} +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* redirect_get_outputs.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/02/23 12:37:24 by Quinten #+# #+# */ +/* Updated: 2025/02/27 18:12:04 by qmennen ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +t_list *redirect_get_outputs(t_minishell *msh, t_list *list) +{ + t_list *current; + t_list *redirects; + t_token *token; + int flag; + + flag = 1; + redirects = NULL; + current = list; + token = (t_token *)current->content; + while (current && !redirect_is_delimiter(token)) + { + token = (t_token *)current->content; + if (token->type != T_REDIRECT_OUT && token->type != T_APPEND_OUT) + { + current = current->next; + continue ; + } + flag = redirect_is_valid(current, token, -1); + flag && (redirect_create(msh, ¤t, &redirects, token->type)); + current = current->next; + } + redirect_new_error(msh, &redirects, flag); + return (redirects); +} diff --git a/src/redirect/redirect_new.c b/src/redirect/redirect_new.c index ee11cf9..79c0951 100644 --- a/src/redirect/redirect_new.c +++ b/src/redirect/redirect_new.c @@ -1,44 +1,45 @@ -/* ************************************************************************** */ -/* */ -/* :::::::: */ -/* redirect_new.c :+: :+: */ -/* +:+ */ -/* By: Quinten +#+ */ -/* +#+ */ -/* Created: 2025/02/23 12:27:33 by Quinten #+# #+# */ -/* Updated: 2025/02/23 12:27:33 by Quinten ######## odam.nl */ -/* */ -/* ************************************************************************** */ - -#include "minishell.h" - -t_redirect *redirect_new(t_minishell *msh, t_token_type type, char *value) -{ - t_redirect *result; - - result = malloc_safe(msh, sizeof(t_redirect)); - result->type = type; - result->value = NULL; - if (value) - result->value = value; - return (result); -} - -void redirect_create(t_minishell *msh, t_list **tokens, t_list **redirects, -t_token_type type) -{ - t_list *new; - t_redirect *redir; - t_token *file_token; - char *file_name; - - file_token = (t_token *)((*tokens)->next->content); - file_name = NULL; - if (file_token) - file_name = ft_strdup_safe(msh, file_token->value); - redir = redirect_new(msh, type, file_name); - new = ft_lstnew_safe(msh, redir); - ft_lstadd_back(redirects, new); - if (tokens) - *tokens = (*tokens)->next; -} +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* redirect_new.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/02/23 12:27:33 by Quinten #+# #+# */ +/* Updated: 2025/02/27 18:11:25 by qmennen ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +t_redirect *redirect_new(t_minishell *msh, t_token_type type, char *value) +{ + t_redirect *result; + + result = malloc_safe(msh, sizeof(t_redirect)); + result->type = type; + result->value = NULL; + if (value) + result->value = value; + return (result); +} + +int redirect_create(t_minishell *msh, t_list **tokens, t_list **redirects, +t_token_type type) +{ + t_list *new; + t_redirect *redir; + t_token *file_token; + char *file_name; + + file_token = (t_token *)((*tokens)->next->content); + file_name = NULL; + if (file_token) + file_name = ft_strdup_safe(msh, file_token->value); + redir = redirect_new(msh, type, file_name); + new = ft_lstnew_safe(msh, redir); + ft_lstadd_back(redirects, new); + if (tokens) + *tokens = (*tokens)->next; + return (1); +} diff --git a/src/redirect/redirect_new_error.c b/src/redirect/redirect_new_error.c index 076e062..24cf75c 100644 --- a/src/redirect/redirect_new_error.c +++ b/src/redirect/redirect_new_error.c @@ -6,17 +6,19 @@ /* By: qmennen +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/02/26 17:37:12 by qmennen #+# #+# */ -/* Updated: 2025/02/26 17:44:49 by qmennen ### ########.fr */ +/* Updated: 2025/02/27 18:07:25 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ #include "minishell.h" -void redirect_new_error(t_minishell *msh, t_list **redirects) +void redirect_new_error(t_minishell *msh, t_list **redirects, int flag) { t_list *new; t_redirect *redir; + if (flag) + return ; redir = redirect_new(msh, T_ERROR, NULL); new = ft_lstnew_safe(msh, redir); ft_lstadd_back(redirects, new); diff --git a/src/token/token_char_convert.c b/src/token/token_char_convert.c new file mode 100644 index 0000000..fbfd1f5 --- /dev/null +++ b/src/token/token_char_convert.c @@ -0,0 +1,38 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* token_char_convert.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/02/27 18:25:34 by qmennen #+# #+# */ +/* Updated: 2025/02/27 18:28:13 by qmennen ### ########.fr */ +/* */ +/* ************************************************************************** */ + +# include "minishell.h" + +t_token_type token_char_convert(char c, int is_double) +{ + if (c == '<') + { + if (is_double) + return (T_HEREDOC); + return (T_REDIRECT_IN); + } + else if (c == '>') + { + if (is_double) + return (T_APPEND_OUT); + return (T_REDIRECT_OUT); + } + else if (c == '&' && is_double) + return (T_AND); + else if (c == '|') + { + if (is_double) + return (T_OR); + return (T_PIPE); + } + return (T_ERROR); +} diff --git a/src/token/token_parse.c b/src/token/token_parse.c index f18eb52..5974479 100644 --- a/src/token/token_parse.c +++ b/src/token/token_parse.c @@ -1,61 +1,17 @@ /* ************************************************************************** */ /* */ -/* :::::::: */ -/* token_parse.c :+: :+: */ -/* +:+ */ -/* By: qmennen +#+ */ -/* +#+ */ -/* Created: 2025/02/05 19:10:17 by qmennen #+# #+# */ -/* Updated: 2025/02/26 16:15:19 by whaffman ######## odam.nl */ +/* ::: :::::::: */ +/* token_parse.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/02/05 19:10:17 by qmennen #+# #+# */ +/* Updated: 2025/02/27 18:27:40 by qmennen ### ########.fr */ /* */ /* ************************************************************************** */ #include "minishell.h" -static t_token_type token_from_char(char c, int is_double) -{ - if (c == '<') - { - if (is_double) - return (T_HEREDOC); - return (T_REDIRECT_IN); - } - else if (c == '>') - { - if (is_double) - return (T_APPEND_OUT); - return (T_REDIRECT_OUT); - } - else if (c == '&' && is_double) - return (T_AND); - else if (c == '|') - { - if (is_double) - return (T_OR); - return (T_PIPE); - } - return (T_ERROR); -} - -static char *char_from_type(t_token_type type) -{ - if (type == T_HEREDOC) - return ("<<"); - else if (type == T_REDIRECT_IN) - return ("<"); - else if (type == T_APPEND_OUT) - return (">>"); - else if (type == T_REDIRECT_OUT) - return (">"); - else if (type == T_AND) - return ("&&"); - else if (type == T_OR) - return ("||"); - else if (type == T_PIPE) - return ("|"); - return (NULL); -} - t_token *token_parse(t_minishell *msh, t_lexer *lexer) { int is_double; @@ -65,8 +21,8 @@ t_token *token_parse(t_minishell *msh, t_lexer *lexer) c = lexer->current_char; is_double = lexer->input[lexer->pos + 1] == c; - type = token_from_char(c, is_double); - token = token_new(msh, type, char_from_type(type), lexer->pos); + type = token_char_convert(c, is_double); + token = token_new(msh, type, token_type_convert(type), lexer->pos); if (is_double) lexer_readchar(lexer); lexer_readchar(lexer); diff --git a/src/token/token_type_convert.c b/src/token/token_type_convert.c new file mode 100644 index 0000000..c42e681 --- /dev/null +++ b/src/token/token_type_convert.c @@ -0,0 +1,32 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* token_type_convert.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: qmennen +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/02/27 18:25:34 by qmennen #+# #+# */ +/* Updated: 2025/02/27 18:26:40 by qmennen ### ########.fr */ +/* */ +/* ************************************************************************** */ + +# include "minishell.h" + +char *token_type_convert(t_token_type type) +{ + if (type == T_HEREDOC) + return ("<<"); + else if (type == T_REDIRECT_IN) + return ("<"); + else if (type == T_APPEND_OUT) + return (">>"); + else if (type == T_REDIRECT_OUT) + return (">"); + else if (type == T_AND) + return ("&&"); + else if (type == T_OR) + return ("||"); + else if (type == T_PIPE) + return ("|"); + return (NULL); +}