/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/05/02 13:22:57 by ljiriste #+# #+# */
-/* Updated: 2024/08/02 18:35:15 by ljiriste ### ########.fr */
+/* Updated: 2024/08/08 15:10:56 by ljiriste ### ########.fr */
/* */
/* ************************************************************************** */
t_vars *vars;
} t_execution_env;
+typedef struct s_wildcard_info
+{
+ const char *to_expand;
+ const char *current_expand_char;
+ const char *entry;
+ const char *current_entry_char;
+ const char *path;
+} t_wildcard_info;
+
typedef t_parse_tree_node t_tree;
int init_env(t_execution_env *env, char **envp);
void handle_input(char **line, t_execution_env *env);
+int add_conformant(t_vec *expanded, t_wildcard_info *info);
+int expand_dir(t_vec *expanded, t_wildcard_info *info);
+
+int expand_wildcards(char **input, const t_execution_env *env);
int tokenize(char **line, t_vec *tokens);
int parse(t_vec *tokens, t_tree **parse_tree);
int execute(t_tree *parse_tree, t_execution_env *env);
void free_token(void *token);
void free_str(void *str);
+const char *get_env_var_value(const t_execution_env *env, const char *var_name);
+char **quoted_split(const char *str);
+
+
#endif // MINISHELL_H
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* wildcards.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2024/08/08 10:50:26 by ljiriste #+# #+# */
+/* Updated: 2024/08/08 15:34:37 by ljiriste ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "minishell.h"
+#include "libft.h"
+#include <stdlib.h>
+#include <sys/types.h>
+#include <dirent.h>
+
+int add_entry(t_vec *expanded, t_wildcard_info *info)
+{
+ char *new_expanded;
+
+ new_expanded = ft_strjoin(info->path, info->entry);
+ if (!new_expanded)
+ return (1);
+ if (ft_vec_append(expanded, &new_expanded) != success)
+ {
+ free(new_expanded);
+ return (1);
+ }
+ return (0);
+}
+
+int branch_at_star(t_vec *expanded, t_wildcard_info *info)
+{
+ const size_t start_size = expanded->size;
+
+ ++info->current_expand_char;
+ if (add_conformant(expanded, info))
+ return (1);
+ if (start_size != expanded->size || *info->current_entry_char == '\0')
+ return (0);
+ --info->current_expand_char;
+ ++info->current_entry_char;
+ return (add_conformant(expanded, info));
+}
+
+int expand_further(t_vec *expanded, t_wildcard_info info)
+{
+ size_t path_len;
+ char *new_path;
+ int res;
+
+ path_len = ft_strlen(info.path) + ft_strlen(info.entry);
+ new_path = malloc(path_len + 2);
+ if (!new_path)
+ return (1);
+ ft_strlcpy(new_path, info.path, path_len + 2);
+ ft_strlcat(new_path, info.entry, path_len + 2);
+ new_path[path_len] = '/';
+ new_path[path_len + 1] = '\0';
+ info.path = new_path;
+ info.to_expand = info.current_expand_char;
+ res = expand_dir(expanded, &info);
+ free(new_path);
+ return (res);
+}
+
+int add_conformant(t_vec *expanded, t_wildcard_info *info)
+{
+ if (*info->current_expand_char == '\0' && *info->current_entry_char == '\0')
+ return (add_entry(expanded, info));
+ if (*info->current_expand_char == '/' && *info->current_entry_char == '\0')
+ {
+ ++info->current_expand_char;
+ return (expand_further(expanded, *info));
+ }
+ if ((*info->current_expand_char == '?' && *info->current_entry_char != '\0')
+ || *info->current_expand_char == *info->current_entry_char)
+ {
+ ++info->current_expand_char;
+ ++info->current_entry_char;
+ return (add_conformant(expanded, info));
+ }
+ if (*info->current_expand_char == '*' && (*info->current_entry_char != '.' || info->current_entry_char != info->entry))
+ return (branch_at_star(expanded, info));
+ return (0);
+}
+
+int expand_dir(t_vec *expanded, t_wildcard_info *info)
+{
+ DIR *dir;
+ struct dirent *dir_entry;
+
+ dir = opendir(info->path);
+ if (!dir)
+ return (0);
+ dir_entry = readdir(dir);
+ while (dir_entry)
+ {
+ info->entry = dir_entry->d_name;
+ info->current_entry_char = info->entry;
+ info->current_expand_char = info->to_expand;
+ if (add_conformant(expanded, info))
+ {
+ closedir(dir);
+ return (1);
+ }
+ dir_entry = readdir(dir);
+ }
+ closedir(dir);
+ return (0);
+}
+
+// Adding one byte more to the str in case '\n' needs o be appended
+int replace_str_by_joint_split(char **str, char **expanded_split)
+{
+ char *tmp;
+ size_t len;
+ size_t i;
+
+ tmp = *str;
+ len = 0;
+ i = 0;
+ while (expanded_split[i])
+ len += ft_strlen(expanded_split[i++]) + 1;
+ *str = malloc(len + 1 + 1);
+ str[0][0] = '\0';
+ if (!str)
+ {
+ *str = tmp;
+ return (1);
+ }
+ i = 0;
+ while (expanded_split[i])
+ {
+ ft_strlcat(*str, expanded_split[i++], len + 1 + 1);
+ ft_strlcat(*str, " ", len + 1 + 1);
+ }
+ free(tmp);
+ return (0);
+}
+
+int expand_word(char **str, const t_execution_env *env)
+{
+ const char *nullptr = NULL;
+ t_vec matched;
+ t_wildcard_info info;
+ int res;
+ char last_char = str[0][ft_strlen(*str) - 1];
+
+ if (last_char == '\n')
+ str[0][ft_strlen(*str) - 1] = '\0';
+ if (ft_vec_init(&matched, sizeof(char *)) != success)
+ return (1);
+ if (str[0][0] == '/')
+ info.path = ft_strdup("/");
+ else if (str[0][0] == '~')
+ info.path = ft_strjoin(get_env_var_value(env, "HOME"), "/");
+ else
+ info.path = ft_strdup("./");
+ if (!info.path)
+ return (1);
+ info.to_expand = *str;
+ res = expand_dir(&matched, &info);
+ res = res || (ft_vec_append(&matched, &nullptr) != success);
+ res = res || replace_str_by_joint_split(str, matched.vec);
+ ft_vec_free(&matched, free_str);
+ free((char *)info.path);
+ if (last_char == '\n')
+ {
+ str[0][ft_strlen(*str) + 1] = '\0';
+ str[0][ft_strlen(*str)] = '\n';
+ }
+ return (res);
+}
+
+int expand_wildcards(char **input, const t_execution_env *env)
+{
+ char **split;
+ size_t i;
+ int res;
+
+ split = quoted_split(*input);
+ if (!split)
+ return (1);
+ i = 0;
+ while (split[i])
+ {
+ if (split[i][0] != '"' && split[i][0] != '\'' && (ft_strchr(split[i], '*') != NULL || ft_strchr(split[i], '?') != NULL))
+ if (expand_word(split + i, env))
+ {
+ ft_free_split(split);
+ return (1);
+ }
+ ++i;
+ }
+ res = replace_str_by_joint_split(input, split);
+ ft_free_split(split);
+ return (res);
+}