/* ************************************************************************** */ /* */ /* ::: :::::::: */ /* expand_token.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: lperrey +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2021/11/07 02:01:33 by lperrey #+# #+# */ /* Updated: 2021/12/16 03:03:27 by lperrey ### ########.fr */ /* */ /* ************************************************************************** */ #include "minishell.h" static t_list *content_copy(char *content, int *i, int *quotes_state); static t_list *content_expand(char *content, int *i); static char *env_var_expansion(char *content, int *i); t_list *expand_token(char *content) { int quotes_state; int i; t_list head; t_list *expand; head.next = NULL; expand = &head; quotes_state = 0; i = 0; while (content[i]) { if (content[i] == '$') expand->next = content_expand(content, &i); else expand->next = content_copy(content, &i, "es_state); expand = expand->next; if (!expand) {//todo wrap perror("expand_token() error"); return (ft_lstclear(&head.next, free)); } } return (head.next); } static t_list *content_copy(char *content, int *i, int *quotes_state) { int i_exp; t_list *expand; expand = ft_lstnew_generic(sizeof(t_list), ft_strlen(&content[*i]) + 1); if (!expand) return (NULL); i_exp = 0; while (content[*i] && (content[*i] != '$' || *quotes_state == IN_QUOTES)) { if (content[*i] == '\'' && *quotes_state != IN_DQUOTES) { if (*quotes_state == IN_QUOTES) *quotes_state = 0; else *quotes_state = IN_QUOTES; } ((char *)expand->content)[i_exp++] = content[(*i)++]; } return (expand); } static t_list *content_expand(char *content, int *i) { t_list *expand; expand = ft_lstnew(NULL); if (!expand) return (NULL); expand->content = env_var_expansion(content, i); if (!expand->content) { free(expand); return (NULL); } return (expand); } static char *retrieve_var(char *content, int *i); static char *env_var_expansion(char *content, int *i) { char *expansion; (*i)++; // skip '$' if (content[*i] == '?') { (*i)++; expansion = ft_itoa(get_last_exit_status()); } else if (content[*i] == '_' || ft_isalpha(content[*i])) expansion = retrieve_var(content, i); else { expansion = ft_calloc(1 + 1, 1); if (!expansion) return (NULL); expansion[0] = '$'; } return (expansion); } static char *retrieve_var(char *content, int *i) { char *expansion; char *tmp; int i_exp; expansion = ft_calloc(ft_strlen(&content[*i - 1]) + 1, 1); // *i - 1 for '$' skip if (!expansion) return (NULL); i_exp = 0; while (content[*i] == '_' || ft_isalnum(content[*i])) expansion[i_exp++] = content[(*i)++]; tmp = getenv(expansion); ft_free_null(&expansion); if (tmp) expansion = ft_strdup(tmp); else expansion = ft_calloc(1, 1); return (expansion); } /* environment variables must be POSIX NAME : 3.235 Name https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html #tag_03_235 */