diff --git a/Makefile b/Makefile index 389f2be..084b2ac 100644 --- a/Makefile +++ b/Makefile @@ -29,6 +29,7 @@ SRCS = main.c init.c free.c generic.c \ parsing.c alloc_cmd_array.c \ valid_syntax.c valid_pipeline.c valid_command.c valid_io_redirect.c \ words_expansions.c expand_token.c rejoin_after_expand.c new_token_for_each_field.c \ + ft_split_quotes.c ft_strdup_quotes.c \ env.c exit.c echo.c DIR_OBJS = builds diff --git a/headers/minishell_prototypes.h b/headers/minishell_prototypes.h index 10c4cd9..088460a 100644 --- a/headers/minishell_prototypes.h +++ b/headers/minishell_prototypes.h @@ -6,7 +6,7 @@ /* By: lperrey +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2021/10/08 02:59:58 by lperrey #+# #+# */ -/* Updated: 2021/11/07 04:13:53 by lperrey ### ########.fr */ +/* Updated: 2021/11/13 04:20:43 by lperrey ### ########.fr */ /* */ /* ************************************************************************** */ @@ -57,5 +57,7 @@ void *ft_resize_2d_arr(void *ptr, size_t add_nbr); void print_matrix(char **matrix, char *sep); t_list *ft_lstbeforelast(t_list *lst); t_list *ft_lstnew_generic(size_t lst_sizse, size_t content_size); +typedef void *(*t_dup_func)(void *); +void *ft_dup_2d_arr(void *ptr, void *(*dup_func)(void *)); #endif diff --git a/headers/minishell_structs.h b/headers/minishell_structs.h index 84f4fc6..742272b 100644 --- a/headers/minishell_structs.h +++ b/headers/minishell_structs.h @@ -6,7 +6,7 @@ /* By: lperrey +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2021/10/08 02:35:52 by lperrey #+# #+# */ -/* Updated: 2021/10/30 13:31:07 by lperrey ### ########.fr */ +/* Updated: 2021/11/11 07:21:47 by lperrey ### ########.fr */ /* */ /* ************************************************************************** */ @@ -23,7 +23,8 @@ enum e_token_id T_PIPE = '|', T_DLESS, T_DGREAT, - T_WORD + T_WORD, + T_REDIRECTION_WORD }; // T_DLESS == '<<' // T_DGREAT == '>>' diff --git a/srcs/generic.c b/srcs/generic.c index 2d56cc4..f9d1839 100644 --- a/srcs/generic.c +++ b/srcs/generic.c @@ -6,7 +6,7 @@ /* By: lperrey +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2021/10/08 09:25:35 by lperrey #+# #+# */ -/* Updated: 2021/11/07 04:07:10 by lperrey ### ########.fr */ +/* Updated: 2021/11/13 04:23:54 by lperrey ### ########.fr */ /* */ /* ************************************************************************** */ @@ -85,7 +85,7 @@ size_t ft_2d_arrlen(void *ptr) // Replace ft_arrlen() return (len); } -char **ft_dup_2d_char_arr(char **ptr) +char **ft_dup_2d_char_arr(char **ptr) // Superflu si ft_dup_2d_arr() fonctionne { unsigned int i; char **arr; @@ -107,6 +107,29 @@ char **ft_dup_2d_char_arr(char **ptr) return (new_arr); } +// Test generic. Pas certain que ça fonctionne bien avec le pointeur sur fonction +void *ft_dup_2d_arr(void *ptr, void *(*dup_func)(void *)) +{ + unsigned int i; + char **arr; + char **new_arr; + + new_arr = malloc((ft_2d_arrlen(ptr) + 1) * sizeof (void *)); + if (!new_arr) + return (NULL); + arr = (char **)ptr; + i = 0; + while (arr[i]) + { + new_arr[i] = dup_func(arr[i]); + if (!new_arr[i]) + return (ft_retp_free(NULL, new_arr, ft_free_2d_arr)); + i++; + } + new_arr[i] = NULL; + return (new_arr); +} + void *ft_resize_2d_arr(void *ptr, size_t add_nbr) { unsigned int i; @@ -151,7 +174,7 @@ t_list *ft_lstbeforelast(t_list *lst) return (lst); } -t_list *ft_lstnew_generic(size_t lst_sizse, size_t content_size) +t_list *ft_lstnew_generic(size_t lst_size, size_t content_size) { t_list *elem; void *content; @@ -164,7 +187,7 @@ t_list *ft_lstnew_generic(size_t lst_sizse, size_t content_size) if (!content) return (NULL); } - elem = ft_calloc(1, lst_sizse); + elem = ft_calloc(1, lst_size); if (!elem) { free(content); diff --git a/srcs/init.c b/srcs/init.c index f6e6484..5052a64 100644 --- a/srcs/init.c +++ b/srcs/init.c @@ -6,7 +6,7 @@ /* By: lperrey +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2021/10/08 09:22:12 by lperrey #+# #+# */ -/* Updated: 2021/11/02 13:50:33 by hulamy ### ########.fr */ +/* Updated: 2021/11/13 05:31:47 by lperrey ### ########.fr */ /* */ /* ************************************************************************** */ @@ -19,9 +19,10 @@ int init(t_all *c, char *envp[]) { g_all = c; ft_bzero(c, sizeof (*c)); - c->envp = ft_dup_2d_char_arr(envp); + c->envp = ft_dup_2d_arr(envp, (t_dup_func)ft_strdup); // TEST WIP if (!c->envp) return (ft_reti_perror(0, "ft_dup_2d_char_arr(envp) error")); + //print_matrix(c->envp, "\n --- \n"); // TEST WIP c->prompt_base = init_prompt_base(); if (!c->prompt_base) return (ft_reti_perror(0, "init_prompt_base() error")); diff --git a/srcs/parsing/alloc_cmd_array.c b/srcs/parsing/alloc_cmd_array.c index edd67c3..b5b3c45 100644 --- a/srcs/parsing/alloc_cmd_array.c +++ b/srcs/parsing/alloc_cmd_array.c @@ -6,7 +6,7 @@ /* By: lperrey +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2021/11/02 22:46:23 by lperrey #+# #+# */ -/* Updated: 2021/11/07 04:29:54 by lperrey ### ########.fr */ +/* Updated: 2021/11/11 08:47:46 by lperrey ### ########.fr */ /* */ /* ************************************************************************** */ @@ -43,6 +43,8 @@ t_cmd **alloc_cmd_array(size_t cmd_nbr) ft_free_2d_arr(cmd_arr); return (ft_retp_perror(NULL, "alloc_cmd()")); } + cmd_arr[i]->fd_in = STDIN_FILENO; + cmd_arr[i]->fd_out = STDOUT_FILENO; i++; } return (cmd_arr); diff --git a/srcs/parsing/expansions/expand_token.c b/srcs/parsing/expansions/expand_token.c index 1b46df2..7885052 100644 --- a/srcs/parsing/expansions/expand_token.c +++ b/srcs/parsing/expansions/expand_token.c @@ -6,7 +6,7 @@ /* By: lperrey +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2021/11/07 02:01:33 by lperrey #+# #+# */ -/* Updated: 2021/11/07 04:36:12 by lperrey ### ########.fr */ +/* Updated: 2021/11/11 21:04:41 by lperrey ### ########.fr */ /* */ /* ************************************************************************** */ @@ -21,9 +21,9 @@ enum e_in_quote_state IN_DQUOTES = '\"' }; -static t_list *ret_parameter_expansion(t_token *t, int *i); +static t_list *ret_parameter_expansion(char *content, int *i); -t_list *expand_token(t_token *t) +t_list *expand_token(char *content) { int in_quotes; int i; @@ -35,11 +35,11 @@ t_list *expand_token(t_token *t) i = 0; head.next = NULL; expand = &head; - while (t->content[i]) + while (content[i]) { - if (t->content[i] == '$') + if (content[i] == '$') { - expand->next = ret_parameter_expansion(t, &i); + expand->next = ret_parameter_expansion(content, &i); expand = expand->next; if (!expand) {//todo wrap @@ -49,7 +49,7 @@ t_list *expand_token(t_token *t) } else { - expand->next = ft_lstnew_generic(sizeof(t_list), ft_strlen(&t->content[i]) + 1); + expand->next = ft_lstnew_generic(sizeof(t_list), ft_strlen(&content[i]) + 1); expand = expand->next; i_exp = 0; if (!expand) @@ -57,17 +57,17 @@ t_list *expand_token(t_token *t) perror("expand_token() error"); return (ft_lstclear(&head.next, free)); } - while (t->content[i] && (t->content[i] != '$' || in_quotes == IN_QUOTES)) + while (content[i] && (content[i] != '$' || in_quotes == IN_QUOTES)) { // quoting - if (t->content[i] == '\'' && in_quotes != IN_DQUOTES) + if (content[i] == '\'' && in_quotes != IN_DQUOTES) { if (in_quotes == IN_QUOTES) in_quotes = 0; else in_quotes = IN_QUOTES; } - ((char *)expand->content)[i_exp++] = t->content[i++]; + ((char *)expand->content)[i_exp++] = content[i++]; } } } @@ -76,35 +76,34 @@ t_list *expand_token(t_token *t) // a voir si je retourne pas plutot un "char *". // Malloc la lst dans la fonction est peut-être un peu superflu et pas super clair. -// et aussi changer "t_token *t" en "char *content", inutile d'avoir le token entier. -static t_list *ret_parameter_expansion(t_token *t, int *i) +static t_list *ret_parameter_expansion(char *content, int *i) { t_list *expand; char *tmp; int i_tmp; - tmp = ft_calloc(ft_strlen(&t->content[*i]) + 1, 1); + tmp = ft_calloc(ft_strlen(&content[*i]) + 1, 1); if (!tmp) return (NULL); expand = ft_lstnew(NULL); if (!expand) return (ft_retp_free(NULL, tmp, free)); (*i)++; // skip '$' - if (t->content[*i] == '?') + if (content[*i] == '?') { (*i)++; expand->content = ft_itoa(g_all->last_exit_status); return (ft_retp_free(expand, tmp, free)); } - else if (t->content[*i] != '_' && !ft_isalpha(t->content[*i])) + else if (content[*i] != '_' && !ft_isalpha(content[*i])) { tmp[0] = '$'; expand->content = tmp; return (expand); } i_tmp = 0; - while (t->content[*i] == '_' || ft_isalnum(t->content[*i])) - tmp[i_tmp++] = t->content[(*i)++]; + while (content[*i] == '_' || ft_isalnum(content[*i])) + tmp[i_tmp++] = content[(*i)++]; expand->content = getenv(tmp); free(tmp); if (expand->content) diff --git a/srcs/parsing/expansions/ft_split_quotes.c b/srcs/parsing/expansions/ft_split_quotes.c new file mode 100644 index 0000000..d235c96 --- /dev/null +++ b/srcs/parsing/expansions/ft_split_quotes.c @@ -0,0 +1,186 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_split_quotes.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: lperrey +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2021/11/13 07:08:40 by lperrey #+# #+# */ +/* Updated: 2021/11/13 22:35:34 by lperrey ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +enum e_in_quote_state +{ + NOT_IN = 0, + IN_QUOTES = '\'', + IN_DQUOTES = '\"' +}; + +static size_t count_word(char const *s, char c); +static char **alloc_words(char const *s, char c, char **str_arr, + size_t words_count); +static void fill_arr(char const *s, char c, char **str_arr); +static int quote_state_change(int *quote_state, const char *s); + +char **ft_split_quotes(char const *s, char c) +{ + char **str_arr; + size_t words_count; + + if (s == NULL) + return (NULL); + words_count = count_word(s, c); + str_arr = ft_calloc(words_count + 1, sizeof(char *)); + if (!str_arr) + return (NULL); + if (!(alloc_words(s, c, str_arr, words_count))) + { + ft_free_2d_arr(str_arr); + return (NULL); + } + fill_arr(s, c, str_arr); + return (str_arr); +} + +static size_t count_word(char const *s, char c) +{ + unsigned int i; + size_t count; + int quote_state; + + i = 0; + count = 0; + quote_state = 0; + while (s[i]) + { + while (s[i] == c) + i++; + if (s[i]) + count++; + while (s[i] && (s[i] != c || quote_state)) + { + while (quote_state_change("e_state, &s[i])) + i++; + if (s[i] != c || quote_state) + i++; + } + } + return (count); +} + +static char **alloc_words(char const *s, char c, char **str_arr, + size_t words_count) +{ + unsigned int i; + size_t len; + unsigned int arr_i; + int quote_state; + + i = 0; + arr_i = 0; + quote_state = 0; + while (arr_i < words_count) + { + len = 0; + while (s[i] == c) + i++; + while (s[i + len] + && (quote_state_change("e_state, &s[i + len]) + || (s[i + len] != c || quote_state))) + len++; + i = i + len; + str_arr[arr_i] = ft_calloc(len + 1, 1); + if (!str_arr[arr_i]) + return (NULL); + arr_i++; + } + return (str_arr); +} + +// Plus clair, plus de 25 lignes :( +/* static char **alloc_words(char const *s, char c, char **str_arr, + size_t words_count) +{ + unsigned int i; + size_t len; + unsigned int arr_i; + int quote_state; + + i = 0; + arr_i = 0; + quote_state = 0; + while (arr_i < words_count) + { + len = 0; + while (s[i] == c) + i++; + while (s[i + len] && (s[i + len] != c || quote_state)) + { + while (quote_state_change("e_state, &s[i + len])) + len++; + if (s[i + len] != c || quote_state) + len++; + } + i = i + len; + str_arr[arr_i] = ft_calloc(len + 1, 1); + if (!str_arr[arr_i]) + return (NULL); + arr_i++; + } + return (str_arr); +} */ + +static void fill_arr(char const *s, char c, char **str_arr) +{ + unsigned int i; + unsigned int arr_i; + unsigned int char_i; + int quote_state; + + i = 0; + arr_i = 0; + quote_state = 0; + while (str_arr[arr_i]) + { + while (s[i] == c) + i++; + char_i = 0; + while (s[i] && (s[i] != c || quote_state)) + { + while (quote_state_change("e_state, &s[i])) + str_arr[arr_i][char_i++] = s[i++]; + if (s[i] != c || quote_state) + str_arr[arr_i][char_i++] = s[i++]; + } + str_arr[arr_i][char_i] = '\0'; //superflu si ft_calloc + arr_i++; + } +} + +static int quote_state_change(int *quote_state, const char *s) +{ + if (s[0] == '\'' && *quote_state != IN_DQUOTES) + { + if (*quote_state == IN_QUOTES) + *quote_state = 0; + else if (ft_strchr(&s[1], '\'')) // if closed quotes + *quote_state = IN_QUOTES; + else + return (0); + return (1); + } + else if (s[0] == '\"' && *quote_state != IN_QUOTES) + { + if (*quote_state == IN_DQUOTES) + *quote_state = 0; + else if (ft_strchr(&s[1], '\"')) // if closed quotes + *quote_state = IN_DQUOTES; + else + return (0); + return (1); + } + return (0); +} diff --git a/srcs/parsing/expansions/ft_strdup_quotes.c b/srcs/parsing/expansions/ft_strdup_quotes.c new file mode 100644 index 0000000..9990472 --- /dev/null +++ b/srcs/parsing/expansions/ft_strdup_quotes.c @@ -0,0 +1,68 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strdup_quotes.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: lperrey +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2021/11/13 04:35:06 by lperrey #+# #+# */ +/* Updated: 2021/11/13 10:18:51 by lperrey ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +enum e_in_quote_state +{ + NOT_IN = 0, + IN_QUOTES = '\'', + IN_DQUOTES = '\"' +}; +static int quote_state_change(int *quote_state, const char *s); + +char *ft_strdup_quotes(const char *s) +{ + unsigned int i; + unsigned int i_dup; + char *dup; + int quote_state; + + dup = ft_calloc(ft_strlen(s) + 1, 1); + if (!dup) + return (NULL); + i = 0; + i_dup = 0; + quote_state = 0; + while (s[i]) + { + while (quote_state_change("e_state, &s[i])) + i++; + dup[i_dup++] = s[i++]; + } + return (dup); +} + +static int quote_state_change(int *quote_state, const char *s) +{ + if (s[0] == '\'' && *quote_state != IN_DQUOTES) + { + if (*quote_state == IN_QUOTES) + *quote_state = 0; + else if (ft_strchr(&s[1], '\'')) // if closed quotes + *quote_state = IN_QUOTES; + else + return (0); + return (1); + } + else if (s[0] == '\"' && *quote_state != IN_QUOTES) + { + if (*quote_state == IN_DQUOTES) + *quote_state = 0; + else if (ft_strchr(&s[1], '\"')) // if closed quotes + *quote_state = IN_DQUOTES; + else + return (0); + return (1); + } + return (0); +} diff --git a/srcs/parsing/expansions/new_token_for_each_field.c b/srcs/parsing/expansions/new_token_for_each_field.c index c3ee91c..38298b9 100644 --- a/srcs/parsing/expansions/new_token_for_each_field.c +++ b/srcs/parsing/expansions/new_token_for_each_field.c @@ -27,16 +27,21 @@ int new_token_for_each_field(char **fields, t_token **t) i = 0; while (fields[i]) { - insert_lst->next = (t_token *)ft_lstnew_generic(sizeof(*insert_lst), 0); - insert_lst = insert_lst->next; - if (!insert_lst) - {//todo wrap - perror("insert_token_for_each_field() error"); - ft_free_2d_arr(fields); - return ((int)ft_lstclear((t_list **)&head.next, NULL)); + if (fields[i][0]) + { + insert_lst->next = (t_token *)ft_lstnew_generic(sizeof(t_token), 0); + insert_lst = insert_lst->next; + if (!insert_lst) + {//todo wrap + perror("insert_token_for_each_field() error"); + ft_free_2d_arr(fields); + return ((int)ft_lstclear((t_list **)&head.next, NULL)); + } + insert_lst->content = fields[i]; + insert_lst->id = T_WORD; } - insert_lst->content = fields[i]; - insert_lst->id = T_WORD; + else + free(fields[i]); i++; } free(fields); diff --git a/srcs/parsing/expansions/words_expansions.c b/srcs/parsing/expansions/words_expansions.c index 36f5288..8c7e356 100644 --- a/srcs/parsing/expansions/words_expansions.c +++ b/srcs/parsing/expansions/words_expansions.c @@ -6,7 +6,7 @@ /* By: lperrey +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2021/11/07 02:01:33 by lperrey #+# #+# */ -/* Updated: 2021/11/08 03:59:02 by lperrey ### ########.fr */ +/* Updated: 2021/11/13 21:27:20 by lperrey ### ########.fr */ /* */ /* ************************************************************************** */ @@ -20,15 +20,18 @@ enum e_in_quote_state }; t_list *ft_lstnew_generic(size_t lst_sizse, size_t content_size); -t_list *expand_token(t_token *t); +t_list *expand_token(char *content); char *rejoin_after_expand(t_list *expand_lst); +char **ft_split_quotes(char const *s, char c); // Generic +char *ft_strdup_quotes(const char *s); // Generic int new_token_for_each_field(char **fields, t_token **t); // 1 - chaque bout dans un element d'une t_list // (telle quelle si non expand, ou VARIABLE de env) // 2 - strjoin() le tout // 3 - split avec un ft_strplit() modifié (ne splitant pas dans les quotes) -// 4 - creer un token T_WORD pour chaque *string du **split_arr +// 4 - quotes removal, ft_strdup_quotes() le tableau split +// 5 - creer un token T_WORD pour chaque *string du **split_arr // (ft_lstadd_front() sur le token original, puis set le token orignal à : // t->id = 0 ; free(t->content) ; t->content = NULL ; pour qu'il soit ignoré sur la suite du parsing) @@ -42,19 +45,25 @@ int words_expansions(t_token *t) if (t->id == T_WORD) { // 1 - tmp_expand = expand_token(t); + tmp_expand = expand_token(t->content); if (!tmp_expand) return (0); // 2 tmp_expand = rejoin_after_expand(tmp_expand); if (!tmp_expand) return (0); - // 3 WIP PLACEHOLDER, MUST WRITE A ft_split_quoted() FOR NO SPLIT IN QUOTES - tmp_split = ft_split(tmp_expand, ' '); + // 3 + tmp_split = ft_split_quotes(tmp_expand, ' '); free(tmp_expand); if (!tmp_split) return (0); // 4 + tmp_expand = ft_dup_2d_arr(tmp_split, (t_dup_func)ft_strdup_quotes); + ft_free_2d_arr(tmp_split); + tmp_split = tmp_expand; + if (!tmp_split) + return (0); + // 5 if (!new_token_for_each_field(tmp_split, &t)) return (0); } diff --git a/srcs/parsing/parsing.c b/srcs/parsing/parsing.c index d55ad04..b314dc0 100644 --- a/srcs/parsing/parsing.c +++ b/srcs/parsing/parsing.c @@ -6,7 +6,7 @@ /* By: lperrey +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2021/10/24 10:52:40 by lperrey #+# #+# */ -/* Updated: 2021/11/08 01:03:29 by lperrey ### ########.fr */ +/* Updated: 2021/11/13 05:13:40 by lperrey ### ########.fr */ /* */ /* ************************************************************************** */ @@ -25,28 +25,72 @@ int next_cmd(t_token *token); int is_redirection(enum e_token_id id); // HUGO WIP +void save_redirections_words(t_token *t) +{ + while (t) + { + if (t->id == '>' || t->id == T_DGREAT + || t->id == '<' || t->id == T_DLESS) + { + t = t->next; + t->id = T_REDIRECTION_WORD; + } + t = t->next; + } +} + +void ft_free_cmd_arr(t_cmd **cmd_arr) +{ + int i; + + i = 0; + while (cmd_arr[i]) + { + if (cmd_arr[i]->argv) + ft_free_2d_arr(cmd_arr[i]->argv); + if (cmd_arr[i]->fd_in != STDIN_FILENO && cmd_arr[i]->fd_in > 0) + if (close(cmd_arr[i]->fd_in) == -1) + perror("close()"); + if (cmd_arr[i]->fd_out != STDOUT_FILENO && cmd_arr[i]->fd_out > 0) + if (close(cmd_arr[i]->fd_out) == -1) + perror("close()"); + i++; + } + ft_free_2d_arr(cmd_arr); +} + t_cmd **parsing(t_token *token_list) { t_cmd **cmd_arr; if (!valid_syntax(token_list)) return (NULL); - // Struct CMD alloc - cmd_arr = alloc_cmd_array(count_pipes(token_list) + 1); - if (!cmd_arr) - return (NULL); + + // 2.9.1 - 1) Save Words + save_redirections_words(token_list); // 2.9.1 - 2) Expansion // TEST TOKENS PRINT ft_putstr_fd("TOKENS LIST :\n-----------\n", 1); ft_lstprint((t_list *)token_list, 1); // - words_expansions(token_list); + // getenv() ne va pas fonctionner avec le changement d'environnement prévu jusqu'ici. + // TODO : Revoir le changement d'environnement (avec extern char **environ ?) + // OU Integrer un equivalent perso comme dans pipex + if (!words_expansions(token_list)) + return (NULL); // ft_putstr_fd("TOKENS LIST EXPANDED :\n-----------\n", 1); ft_lstprint((t_list *)token_list, 1); + // Struct CMD alloc + cmd_arr = alloc_cmd_array(1 + count_pipes(token_list)); + if (!cmd_arr) + return (NULL); + // 2.9.1 - 3) Redirection +/* if (!redirections(token_list, cmd_arr)) + return (ft_retp_free(NULL, cmd_arr, ft_free_cmd_arr)); */ // Struct CMD fill diff --git a/srcs/parsing/redirections.c b/srcs/parsing/redirections.c new file mode 100644 index 0000000..b9fa650 --- /dev/null +++ b/srcs/parsing/redirections.c @@ -0,0 +1,100 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* redirections.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: lperrey +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2021/11/11 18:46:43 by lperrey #+# #+# */ +/* Updated: 2021/11/12 20:17:09 by lperrey ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +int ft_reti_perror_io(int ret, char *err_str, char *io_file) // generic +{ + ft_putstr_fd(err_str, 2); + perror(io_file); + return (ret); +} + +int here_doc_handle_PLACEHOLDER(char *delimiter) +{ + // https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_07_04 + // https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_02 + /* If any part of word is quoted, + the delimiter shall be formed by performing quote removal on word, + and the here-document lines shall not be expanded. + Otherwise, the delimiter shall be the word itself. */ + // Pas d'expansion sur le delimiter, mais quote removal tout de même. + // TODO : quote removal sur le delimiter. + QUOTE_REMOVAL_PLACEHOLDER(); +} + +int redirect_cmd_input(t_token *t, t_cmd *cmd) +{ + if (cmd->fd_in != STDIN_FILENO && cmd->fd_in > 0) + if (close(cmd->fd_in) == -1) + perror("close()"); + if (t->id == '<') + { + // TODO : Expansion + quote removal sur le word t->next->content. + // si plus d'un champ ou aucun champ aprés expansion, + // message d'erreur comme bash "bash: $VAR: ambiguous redirect" + // OU prise en compte seulement du premier champ. + EXPAND_AND_QUOTE_REMOVAL_PLACEHOLDER(); + cmd->fd_in = open(t->next->content, O_RDONLY); + if (cmd->fd_in == -1) + ft_reti_perror_io(0, "open() ", t->next->content); + } + else if (t->id == T_DLESS) + cmd->fd_in = here_doc_handle_PLACEHOLDER(t->next->content); // TODO + return (1); +} + +int redirect_cmd_output(t_token *t, t_cmd *cmd) +{ + int flags; + + if (cmd->fd_out != STDOUT_FILENO && cmd->fd_out > 0) + if (close(cmd->fd_out) == -1) + perror("close()"); + // TODO : Expansion + quote removal sur le word t->next->content. + // si plus d'un champ ou aucun champ aprés expansion, + // message d'erreur comme bash "bash: $VAR: ambiguous redirect" + // OU prise en compte seulement du premier champ. + EXPAND_AND_QUOTE_REMOVAL_PLACEHOLDER(); + if (t->id == '>') + flags = O_WRONLY | O_CREAT | O_TRUNC; + else if (t->id == T_DGREAT) + flags = O_WRONLY | O_CREAT | O_APPEND; + cmd->fd_out = open(t->next->content, flags, S_IRWXU); + if (cmd->fd_out == -1) + return (ft_reti_perror_io(0, "open() ", t->next->content)); + return (1); +} + +int redirections(t_token *t, t_cmd **cmd_arr) +{ + int i; + + i = 0; + while (t) + { + if (t->id == '<' || t->id == T_DLESS) + { + if (!redirect_cmd_input(t, cmd_arr[i])) + return (0); + } + else if (t->id == '>' || t->id == T_DGREAT) + { + if (!redirect_cmd_output(t, cmd_arr[i])) + return (0); + } + else if (t->id == '|') + i++; + t = t->next; + } + return (1); +} diff --git a/srcs/shell_loop.c b/srcs/shell_loop.c index 0e7349e..905d080 100644 --- a/srcs/shell_loop.c +++ b/srcs/shell_loop.c @@ -6,7 +6,7 @@ /* By: lperrey +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2021/10/04 05:59:26 by lperrey #+# #+# */ -/* Updated: 2021/11/02 22:38:35 by lperrey ### ########.fr */ +/* Updated: 2021/11/08 05:16:48 by lperrey ### ########.fr */ /* */ /* ************************************************************************** */ @@ -32,14 +32,18 @@ void shell_loop(t_all *c) if (line_input && *line_input) { add_history(line_input); - //test_signal(c); // Lexing c->token_list = input_to_tokens(line_input); + if (!c->token_list) + continue ; // Parsing c->cmd_arr = parsing(c->token_list); ft_lstclear((t_list **)&c->token_list, free); + if (!c->cmd_arr) + continue ; // Search Path/builtins - // Exec + // Bien penser à mettre les ptr à NULL aprés free en cas d'erreur (pour ne pas double free si appel à free_exit()) + // Exec Pipeline //execute_cmd(c->envp, c->cmd_arr); } else if (!line_input) diff --git a/valgrind_invalid_read_to_fix.txt b/valgrind_invalid_read_to_fix.txt new file mode 100644 index 0000000..a9ee338 --- /dev/null +++ b/valgrind_invalid_read_to_fix.txt @@ -0,0 +1,157 @@ +lucky@Tour-Lemdows10:/mnt/c/Users/Lucky/Desktop/code/minishell> 3[5;6;35 +TOKENS LIST : +----------- +3[5;6;35 +TOKENS LIST EXPANDED : +----------- +3[5;6;35 +lucky@Tour-Lemdows10:/mnt/c/Users/Lucky/Desktop/code/minishell> [6;34'.6' +TOKENS LIST : +----------- +[6;34'.6' +==2095== Invalid read of size 1 +==2095== at 0x403938: count_word (ft_split_quotes.c:63) +==2095== by 0x403806: ft_split_quotes (ft_split_quotes.c:35) +==2095== by 0x402FC0: words_expansions (words_expansions.c:56) +==2095== by 0x40275E: parsing (parsing.c:80) +==2095== by 0x401A6E: shell_loop (shell_loop.c:40) +==2095== by 0x400DA0: main (main.c:25) +==2095== Address 0x56d265a is 0 bytes after a block of size 10 alloc'd +==2095== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) +==2095== by 0x4048A8: ft_strjoin (ft_strjoin.c:23) +==2095== by 0x40115C: ft_strjoinfree_s1 (generic.c:29) +==2095== by 0x40358F: rejoin_after_expand (rejoin_after_expand.c:29) +==2095== by 0x402F97: words_expansions (words_expansions.c:52) +==2095== by 0x40275E: parsing (parsing.c:80) +==2095== by 0x401A6E: shell_loop (shell_loop.c:40) +==2095== by 0x400DA0: main (main.c:25) +==2095== +==2095== Invalid read of size 1 +==2095== at 0x4038D1: count_word (ft_split_quotes.c:57) +==2095== by 0x403806: ft_split_quotes (ft_split_quotes.c:35) +==2095== by 0x402FC0: words_expansions (words_expansions.c:56) +==2095== by 0x40275E: parsing (parsing.c:80) +==2095== by 0x401A6E: shell_loop (shell_loop.c:40) +==2095== by 0x400DA0: main (main.c:25) +==2095== Address 0x56d265a is 0 bytes after a block of size 10 alloc'd +==2095== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) +==2095== by 0x4048A8: ft_strjoin (ft_strjoin.c:23) +==2095== by 0x40115C: ft_strjoinfree_s1 (generic.c:29) +==2095== by 0x40358F: rejoin_after_expand (rejoin_after_expand.c:29) +==2095== by 0x402F97: words_expansions (words_expansions.c:52) +==2095== by 0x40275E: parsing (parsing.c:80) +==2095== by 0x401A6E: shell_loop (shell_loop.c:40) +==2095== by 0x400DA0: main (main.c:25) +==2095== +==2095== Invalid read of size 1 +==2095== at 0x403C0F: fill_arr (ft_split_quotes.c:151) +==2095== by 0x403888: ft_split_quotes (ft_split_quotes.c:44) +==2095== by 0x402FC0: words_expansions (words_expansions.c:56) +==2095== by 0x40275E: parsing (parsing.c:80) +==2095== by 0x401A6E: shell_loop (shell_loop.c:40) +==2095== by 0x400DA0: main (main.c:25) +==2095== Address 0x56d265a is 0 bytes after a block of size 10 alloc'd +==2095== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) +==2095== by 0x4048A8: ft_strjoin (ft_strjoin.c:23) +==2095== by 0x40115C: ft_strjoinfree_s1 (generic.c:29) +==2095== by 0x40358F: rejoin_after_expand (rejoin_after_expand.c:29) +==2095== by 0x402F97: words_expansions (words_expansions.c:52) +==2095== by 0x40275E: parsing (parsing.c:80) +==2095== by 0x401A6E: shell_loop (shell_loop.c:40) +==2095== by 0x400DA0: main (main.c:25) +==2095== +==2095== Invalid write of size 1 +==2095== at 0x403D30: fill_arr (ft_split_quotes.c:158) +==2095== by 0x403888: ft_split_quotes (ft_split_quotes.c:44) +==2095== by 0x402FC0: words_expansions (words_expansions.c:56) +==2095== by 0x40275E: parsing (parsing.c:80) +==2095== by 0x401A6E: shell_loop (shell_loop.c:40) +==2095== by 0x400DA0: main (main.c:25) +==2095== Address 0x56d26fa is 0 bytes after a block of size 10 alloc'd +==2095== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) +==2095== by 0x404760: ft_calloc (ft_calloc.c:19) +==2095== by 0x403B3C: alloc_words (ft_split_quotes.c:95) +==2095== by 0x403852: ft_split_quotes (ft_split_quotes.c:39) +==2095== by 0x402FC0: words_expansions (words_expansions.c:56) +==2095== by 0x40275E: parsing (parsing.c:80) +==2095== by 0x401A6E: shell_loop (shell_loop.c:40) +==2095== by 0x400DA0: main (main.c:25) +==2095== +==2095== Invalid read of size 1 +==2095== at 0x403EE2: ft_strdup_quotes (ft_strdup_quotes.c:36) +==2095== by 0x40149A: ft_dup_2d_arr (generic.c:124) +==2095== by 0x402FFA: words_expansions (words_expansions.c:61) +==2095== by 0x40275E: parsing (parsing.c:80) +==2095== by 0x401A6E: shell_loop (shell_loop.c:40) +==2095== by 0x400DA0: main (main.c:25) +==2095== Address 0x56d26fa is 0 bytes after a block of size 10 alloc'd +==2095== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) +==2095== by 0x404760: ft_calloc (ft_calloc.c:19) +==2095== by 0x403B3C: alloc_words (ft_split_quotes.c:95) +==2095== by 0x403852: ft_split_quotes (ft_split_quotes.c:39) +==2095== by 0x402FC0: words_expansions (words_expansions.c:56) +==2095== by 0x40275E: parsing (parsing.c:80) +==2095== by 0x401A6E: shell_loop (shell_loop.c:40) +==2095== by 0x400DA0: main (main.c:25) +==2095== +TOKENS LIST EXPANDED : +----------- +[6;34.6 +lucky@Tour-Lemdows10:/mnt/c/Users/Lucky/Desktop/code/minishell> ^D==2095== +==2095== FILE DESCRIPTORS: 3 open at exit. +==2095== Open file descriptor 2: /dev/tty1 +==2095== +==2095== +==2095== Open file descriptor 1: /dev/tty1 +==2095== +==2095== +==2095== Open file descriptor 0: /dev/tty1 +==2095== +==2095== +==2095== +==2095== HEAP SUMMARY: +==2095== in use at exit: 134,842 bytes in 208 blocks +==2095== total heap usage: 557 allocs, 349 frees, 165,633 bytes allocated +==2095== +==2095== 16 bytes in 1 blocks are still reachable in loss record 7 of 46 +==2095== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) +==2095== by 0x404760: ft_calloc (ft_calloc.c:19) +==2095== by 0x40284F: alloc_cmd_array (alloc_cmd_array.c:34) +==2095== by 0x4027AB: parsing (parsing.c:87) +==2095== by 0x401A6E: shell_loop (shell_loop.c:40) +==2095== by 0x400DA0: main (main.c:25) +==2095== +==2095== 32 bytes in 1 blocks are still reachable in loss record 10 of 46 +==2095== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) +==2095== by 0x404760: ft_calloc (ft_calloc.c:19) +==2095== by 0x4028A3: alloc_cmd_array (alloc_cmd_array.c:40) +==2095== by 0x4027AB: parsing (parsing.c:87) +==2095== by 0x401A6E: shell_loop (shell_loop.c:40) +==2095== by 0x400DA0: main (main.c:25) +==2095== +==2095== 224 bytes in 7 blocks are indirectly lost in loss record 19 of 46 +==2095== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) +==2095== by 0x404760: ft_calloc (ft_calloc.c:19) +==2095== by 0x4028A3: alloc_cmd_array (alloc_cmd_array.c:40) +==2095== by 0x4027AB: parsing (parsing.c:87) +==2095== by 0x401A6E: shell_loop (shell_loop.c:40) +==2095== by 0x400DA0: main (main.c:25) +==2095== +==2095== 336 (112 direct, 224 indirect) bytes in 7 blocks are definitely lost in loss record 21 of 46 +==2095== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) +==2095== by 0x404760: ft_calloc (ft_calloc.c:19) +==2095== by 0x40284F: alloc_cmd_array (alloc_cmd_array.c:34) +==2095== by 0x4027AB: parsing (parsing.c:87) +==2095== by 0x401A6E: shell_loop (shell_loop.c:40) +==2095== by 0x400DA0: main (main.c:25) +==2095== +==2095== LEAK SUMMARY: +==2095== definitely lost: 112 bytes in 7 blocks +==2095== indirectly lost: 224 bytes in 7 blocks +==2095== possibly lost: 0 bytes in 0 blocks +==2095== still reachable: 48 bytes in 2 blocks +==2095== suppressed: 134,458 bytes in 192 blocks +==2095== +==2095== For counts of detected and suppressed errors, rerun with: -v +==2095== ERROR SUMMARY: 6 errors from 6 contexts (suppressed: 0 from 0) +➜ minishell git:(master) ✗