diff options
| author | Charles <sircharlesaze@gmail.com> | 2020-06-09 10:53:57 +0200 |
|---|---|---|
| committer | Charles <sircharlesaze@gmail.com> | 2020-06-09 10:53:57 +0200 |
| commit | c16cf5fcc4a421608bf3c291ef84a79b7dbe7591 (patch) | |
| tree | 2c7b814f7e9eee40d34a6cf26b4948c39fecfc4c | |
| parent | 9dca7dc98e46d5b29e236f2970072ffaf582e13e (diff) | |
| parent | 9fabc25a980550afc6337fd729632462f2680daa (diff) | |
| download | minishell-c16cf5fcc4a421608bf3c291ef84a79b7dbe7591.tar.gz minishell-c16cf5fcc4a421608bf3c291ef84a79b7dbe7591.tar.bz2 minishell-c16cf5fcc4a421608bf3c291ef84a79b7dbe7591.zip | |
Merge branch 'eval'
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | README.md | 4 | ||||
| -rw-r--r-- | include/ast.h | 17 | ||||
| -rw-r--r-- | include/eval.h | 22 | ||||
| -rw-r--r-- | include/minishell.h | 8 | ||||
| -rw-r--r-- | include/ms_glob.h | 32 | ||||
| -rw-r--r-- | include/utils.h | 31 | ||||
| m--------- | libft | 0 | ||||
| -rw-r--r-- | src/ast.c | 16 | ||||
| -rw-r--r-- | src/builtin/cd.c | 11 | ||||
| -rw-r--r-- | src/builtin/echo.c | 6 | ||||
| -rw-r--r-- | src/builtin/export.c | 6 | ||||
| -rw-r--r-- | src/builtin/unset.c | 5 | ||||
| -rw-r--r-- | src/env.c | 41 | ||||
| -rw-r--r-- | src/eval/eval.c | 148 | ||||
| -rw-r--r-- | src/glob.c | 162 | ||||
| -rw-r--r-- | src/main.c | 64 | ||||
| -rw-r--r-- | src/path.c | 28 | ||||
| -rw-r--r-- | src/preprocess.c | 69 | ||||
| -rw-r--r-- | src/utils.c | 54 |
20 files changed, 577 insertions, 149 deletions
@@ -6,7 +6,7 @@ # By: cacharle <marvin@42.fr> +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2020/02/03 04:14:24 by cacharle #+# #+# # -# Updated: 2020/04/01 18:08:25 by charles ### ########.fr # +# Updated: 2020/04/03 13:50:17 by charles ### ########.fr # # # # **************************************************************************** # @@ -18,8 +18,8 @@ You can then read the man pages in ./doc/man or open ./doc/html/index.html in yo ### Mandatory - [ ] Show a prompt when waiting for a new command -- [ ] Search and launch the right executable (based on the *PATH* variable or by using relative or absolute path) like in bash @HappyTramp -- [ ] It must implement the builtins like in bash: @nass1pro +- [x] Search and launch the right executable (based on the *PATH* variable or by using relative or absolute path) like in bash +- [ ] It must implement the builtins like in bash: - [ ] `echo` with option `-n` - [ ] `cd` without `-` option - [ ] `pwd` without any options diff --git a/include/ast.h b/include/ast.h index 0d14779..b725c8b 100644 --- a/include/ast.h +++ b/include/ast.h @@ -6,7 +6,7 @@ /* By: charles <charles.cabergs@gmail.com> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/04/01 17:05:38 by charles #+# #+# */ -/* Updated: 2020/04/01 17:52:43 by charles ### ########.fr */ +/* Updated: 2020/05/04 11:59:43 by charles ### ########.fr */ /* */ /* ************************************************************************** */ @@ -25,10 +25,10 @@ /* ** \brief Separator type -** \param SEP_END Regular command end `;` -** \param SEP_PIPE Pipe output of left to right `|` -** \param SEP_AND Execute right if left status == 0 `&&` -** \param SEP_OR Execute right if left status != 0 `||` +** \param SEP_END `;` Regular command end +** \param SEP_PIPE `|` Pipe output of left to right +** \param SEP_AND `&&` Execute right if left status == 0 +** \param SEP_OR `||` Execute right if left status != 0 */ typedef enum e_sep @@ -87,9 +87,8 @@ typedef enum e_ast_tag /* ** \brief AST node struct ** \param tag Node tag -** \param data Union containning possible node data -** \param data::cmd Command struct -** \param data::line Line struct +** \param cmd Command struct +** \param line Line struct */ typedef struct s_ast @@ -99,7 +98,7 @@ typedef struct s_ast { t_line line; t_cmd cmd; - } data; + } ; } t_ast; t_ast *ast_new(t_ast_tag tag, void *data); diff --git a/include/eval.h b/include/eval.h index 31f729b..fc149b2 100644 --- a/include/eval.h +++ b/include/eval.h @@ -6,7 +6,7 @@ /* By: charles <charles.cabergs@gmail.com> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/04/01 17:05:30 by charles #+# #+# */ -/* Updated: 2020/04/01 17:53:26 by charles ### ########.fr */ +/* Updated: 2020/05/04 11:58:16 by charles ### ########.fr */ /* */ /* ************************************************************************** */ @@ -27,8 +27,7 @@ typedef struct { - int pipe_in[2]; - int pipe_out[2]; + int p[2]; t_path path; t_env env; } t_eval_state; @@ -43,11 +42,26 @@ typedef struct s_eval_status int status; } t_eval_status; +typedef struct +{ + t_eval_state *state; + t_line *line; + int fd_in; + int fd_out; +} t_fork_param_line; + +typedef struct +{ + char *exec_path; + char **argv; + char **envp; +} t_fork_param_execve; + /* ** eval.c */ -int eval(t_eval_state *state, t_ast *ast); +int eval(int fd_in, int fd_out, t_eval_state *state, t_ast *ast); /* ** exec.c diff --git a/include/minishell.h b/include/minishell.h index ac00875..9551c1f 100644 --- a/include/minishell.h +++ b/include/minishell.h @@ -6,7 +6,7 @@ /* By: cacharle <marvin@42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/02/26 15:33:51 by cacharle #+# #+# */ -/* Updated: 2020/04/01 22:13:47 by charles ### ########.fr */ +/* Updated: 2020/04/05 14:52:20 by charles ### ########.fr */ /* */ /* ************************************************************************** */ @@ -34,6 +34,7 @@ # include "libft_lst.h" # include "libft_util.h" # include "libft_vec.h" +# include "libft_dstr.h" /* ** \brief Value of pipe entry if closed @@ -70,6 +71,7 @@ t_path path_update(t_path path, char *path_var); t_env env_from_array(char **envp); char *env_search(t_env env, char *key); +char *env_search_first_match(t_env env, const char *haystack); /* ** builtin*.c - directory with all builtin commands @@ -104,9 +106,9 @@ int builtin_env(char **argv, t_env env); int builtin_exit(char **argv, t_env env); /* -** util.c - various utilitary functions +** preprocess.c */ -void ht_del_str_entry(t_ftht_entry *entry); +char *preprocess(char *input, t_env env); #endif diff --git a/include/ms_glob.h b/include/ms_glob.h new file mode 100644 index 0000000..774d3be --- /dev/null +++ b/include/ms_glob.h @@ -0,0 +1,32 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ms_glob.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: charles <charles.cabergs@gmail.com> +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2020/04/05 11:45:11 by charles #+# #+# */ +/* Updated: 2020/04/05 13:05:10 by charles ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef MS_GLOB_H +# define MS_GLOB_H + +# include <dirent.h> +# include <unistd.h> +# include <stddef.h> +# include "libft_str.h" +# include "libft_vec.h" +# include "utils.h" + +struct s_glob_param +{ + char *pattern; + t_ftvec *matches; +}; + +t_ftvec *glob_matches(char *pattern); +char *ms_glob(char *pattern); + +#endif diff --git a/include/utils.h b/include/utils.h new file mode 100644 index 0000000..6f2fbc9 --- /dev/null +++ b/include/utils.h @@ -0,0 +1,31 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* utils.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: charles <charles.cabergs@gmail.com> +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2020/04/05 12:05:49 by charles #+# #+# */ +/* Updated: 2020/04/05 14:51:38 by charles ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef UTILS_H +# define UTILS_H + +/* +** \file utils.h +** \brief Various utilitary functions +*/ + +typedef int (*t_directory_iter_func)(char*, struct dirent*, void*); + +int utils_directory_iter( + char *dirname, + void *param, + t_directory_iter_func f +); + +size_t utils_var_end(char *name); + +#endif diff --git a/libft b/libft -Subproject 1925805cc760061d5742f9d215998561fcd4521 +Subproject 3a2d19df9e509d0b015c786eb02f8315ff0ad91 @@ -6,7 +6,7 @@ /* By: charles <charles.cabergs@gmail.com> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/04/01 17:05:42 by charles #+# #+# */ -/* Updated: 2020/04/01 17:05:44 by charles ### ########.fr */ +/* Updated: 2020/05/04 12:00:20 by charles ### ########.fr */ /* */ /* ************************************************************************** */ @@ -36,9 +36,9 @@ t_ast *ast_new(t_ast_tag tag, void *data) ft_bzero(ast, sizeof(t_ast)); ast->tag = tag; if (tag == TAG_CMD) - ft_memcpy(&ast->data.cmd, (t_cmd*)data, sizeof(t_cmd)); + ft_memcpy(&ast->cmd, (t_cmd*)data, sizeof(t_cmd)); else if (tag == TAG_LINE) - ft_memcpy(&ast->data.line, (t_line*)data, sizeof(t_line)); + ft_memcpy(&ast->line, (t_line*)data, sizeof(t_line)); return (ast); } @@ -53,14 +53,14 @@ void ast_destroy(t_ast *ast) return ; if (ast->tag == TAG_CMD) { - ft_split_destroy(ast->data.cmd.argv); - free(ast->data.cmd.in); - free(ast->data.cmd.out); + ft_split_destroy(ast->cmd.argv); + free(ast->cmd.in); + free(ast->cmd.out); } else if (ast->tag == TAG_LINE) { - ast_destroy(ast->data.line.left); - ast_destroy(ast->data.line.right); + ast_destroy(ast->line.left); + ast_destroy(ast->line.right); } free(ast); } diff --git a/src/builtin/cd.c b/src/builtin/cd.c index 66f1f81..ed0b3cc 100644 --- a/src/builtin/cd.c +++ b/src/builtin/cd.c @@ -6,7 +6,7 @@ /* By: charles <charles.cabergs@gmail.com> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/04/01 17:10:20 by charles #+# #+# */ -/* Updated: 2020/04/01 22:15:49 by charles ### ########.fr */ +/* Updated: 2020/04/03 12:11:52 by charles ### ########.fr */ /* */ /* ************************************************************************** */ @@ -19,14 +19,11 @@ int builtin_cd(char **argv, t_env env) { - char *path; - - path = argv[1]; + //change $PWD + (void)env; if (argv[1] == NULL) - path = env_search(env, "HOME"); - if (path == NULL) return (1); - if (chdir(path) == -1) + if (chdir(argv[1]) == -1) return (1); return (0); } diff --git a/src/builtin/echo.c b/src/builtin/echo.c index 9b7a8f6..886c2ca 100644 --- a/src/builtin/echo.c +++ b/src/builtin/echo.c @@ -6,7 +6,7 @@ /* By: charles <charles.cabergs@gmail.com> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/04/01 17:10:47 by charles #+# #+# */ -/* Updated: 2020/04/01 17:10:48 by charles ### ########.fr */ +/* Updated: 2020/04/02 11:18:16 by charles ### ########.fr */ /* */ /* ************************************************************************** */ @@ -22,8 +22,8 @@ int builtin_echo(char **argv, t_env env) bool newline; (void)env; - newline = ft_strcmp(argv[1], "-n") == 0; - if (newline) + newline = !ft_strcmp(argv[1], "-n") == 0; + if (!newline) argv++; while (*++argv != NULL) { diff --git a/src/builtin/export.c b/src/builtin/export.c index 650a421..1d362b3 100644 --- a/src/builtin/export.c +++ b/src/builtin/export.c @@ -6,7 +6,7 @@ /* By: charles <charles.cabergs@gmail.com> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/04/01 17:11:34 by charles #+# #+# */ -/* Updated: 2020/04/01 22:37:47 by charles ### ########.fr */ +/* Updated: 2020/04/03 12:11:38 by charles ### ########.fr */ /* */ /* ************************************************************************** */ @@ -21,11 +21,13 @@ int builtin_export(char **argv, t_env env) { char *tmp; + // modify existing + // set with no string without '=' if (ft_strchr(argv[1], '=') == NULL) return (1); if ((tmp = ft_strdup(argv[1])) == NULL) return (2); - if (ft_vecpush(env, tmp) == NULL) + if (ft_vecinsert(env, env->size - 1, tmp) == NULL) return (2); // internal error code return (0); } diff --git a/src/builtin/unset.c b/src/builtin/unset.c index ffcf60f..146b755 100644 --- a/src/builtin/unset.c +++ b/src/builtin/unset.c @@ -6,7 +6,7 @@ /* By: charles <charles.cabergs@gmail.com> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/04/01 17:10:51 by charles #+# #+# */ -/* Updated: 2020/04/01 23:05:33 by charles ### ########.fr */ +/* Updated: 2020/04/02 11:17:03 by charles ### ########.fr */ /* */ /* ************************************************************************** */ @@ -25,10 +25,13 @@ int builtin_unset(char **argv, t_env env) return (1); i = 0; while (i < env->size) + { if (ft_strncmp(env->data[i], argv[1], ft_strlen(argv[1])) == 0) { ft_vecremove(env, i, free); return (0); } + i++; + } return (1); } @@ -6,7 +6,7 @@ /* By: cacharle <marvin@42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/02/28 09:21:24 by cacharle #+# #+# */ -/* Updated: 2020/04/01 23:09:33 by charles ### ########.fr */ +/* Updated: 2020/04/05 14:42:38 by charles ### ########.fr */ /* */ /* ************************************************************************** */ @@ -17,6 +17,8 @@ #include "minishell.h" +#define ENV_VEC_DEFAULT_SIZE 64 + /* ** \brief Convert array of string to environment hash table ** \param envp array of string (each in the format `name=value`) @@ -26,26 +28,19 @@ t_env env_from_array(char **envp) { t_env env; - size_t i; - i = 0; - while (envp[i] != NULL) - if (ft_strchr(envp[i++], '=') == NULL) - return (NULL); - if ((env = ft_vecnew(i)) == NULL) + if ((env = ft_vecnew(ENV_VEC_DEFAULT_SIZE)) == NULL) return (NULL); - env->size = i; - i = 0; - while (envp[i] != NULL) + while (*envp != NULL) { - if ((env->data[i] = ft_strdup(envp[i])) == NULL) + if (ft_vecpush_safe(env, ft_strdup(*envp)) == NULL) { ft_vecdestroy(env, free); return (NULL); } - i++; + envp++; } - return (env); + return (ft_vecpush(env, NULL)); } /** @@ -55,6 +50,7 @@ t_env env_from_array(char **envp) ** \return Value after '=' in environment variable array or NULL if not found */ +// could be a wrapper around ft_lfind char *env_search(t_env env, char *key) { size_t i; @@ -68,3 +64,22 @@ char *env_search(t_env env, char *key) } return (NULL); } + +char *env_search_first_match(t_env env, const char *haystack) +{ + int len; + size_t i; + + if (ft_isdigit(*haystack)) + return (NULL); + len = 0; + while (ft_isalnum(haystack[len]) || haystack[len] == '_') + len++; + while (i < env->size) + { + if (ft_strncmp((char*)env->data[i], haystack, len) == 0) + return (ft_strchr((char*)env->data[i], '=') + 1); + i++; + } + return (NULL); +} diff --git a/src/eval/eval.c b/src/eval/eval.c index 8c1e509..0270024 100644 --- a/src/eval/eval.c +++ b/src/eval/eval.c @@ -6,7 +6,7 @@ /* By: charles <charles.cabergs@gmail.com> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/04/01 17:05:21 by charles #+# #+# */ -/* Updated: 2020/04/01 23:15:16 by charles ### ########.fr */ +/* Updated: 2020/05/04 12:00:38 by charles ### ########.fr */ /* */ /* ************************************************************************** */ @@ -18,24 +18,55 @@ #include "eval.h" /* -** \brief Evaluate a line -** \param state State of the evaluation -** \param line Line to evaluate -** \return Last Executed command status or -1 on error +** \brief Wrap a function in a fork +** \param fd_in fork input file descriptor +** \param fd_out fork output file descriptor +** \param passed param of the wrapped function +** \param wrapped function to wrap */ -static int eval_line(t_eval_state *state, t_line *line) +int fork_wrap( + int fd_in, + int fd_out, + void *passed, + int (*wrapped)(void *param)) { - int status; + int status; + pid_t child_pid; - if (line->right == NULL) - return (eval(state, line->left)); - if ((status = eval(state, line->left)) == -1) + if ((child_pid = fork()) == -1) return (-1); - if ((line->sep == SEP_AND && status != 0) || - (line->sep == SEP_OR && status == 0)) - return (status); - return (eval(state, line->right)); + if (child_pid == 0) + { + if (dup2(STDIN_FILENO, fd_in) == -1 || + dup2(STDOUT_FILENO, fd_out) == -1) + exit(EXIT_FAILURE); + if ((status = wrapped(passed)) == -1) + exit(EXIT_FAILURE); + exit(status); + } + wait(&child_pid); + return (WEXITSTATUS(child_pid)); +} + +int run_builtin(t_eval_state *state, char **argv) +{ + return (builtin_dispatch_run(argv, state->env)); +} + +/* +** \brief execve syscall wrapper passed it to fork_wrap +** \param param function params +** \return execve return value +*/ + +int execve_wrapper(void *param) +{ + return (execve( + ((t_fork_param_execve*)param)->exec_path, + ((t_fork_param_execve*)param)->argv, + ((t_fork_param_execve*)param)->envp + )); } /* @@ -45,48 +76,85 @@ static int eval_line(t_eval_state *state, t_line *line) ** \return Executable status or -1 on error */ -static int eval_cmd(t_eval_state *state, t_cmd *cmd) +static int eval_cmd(int fd_in, int fd_out, t_eval_state *state, t_cmd *cmd) { - int child_pid; - char *exec_path; - bool is_builtin; + t_fork_param_execve param; - is_builtin = builtin_check_exec_name(cmd->argv[0]); // no fork if builtin - if (!is_builtin) - { - if ((exec_path = exec_search_path(state->path, - env_search(state->env, "PATH"), cmd->argv[0])) == NULL) - return (-1); - } - pipe_setup_parent(cmd, state->pipe_in, state->pipe_out); - if ((child_pid = fork()) == -1) + if (builtin_check_exec_name(cmd->argv[0])) + return (run_builtin(state, cmd->argv)); + param.exec_path = exec_search_path( + state->path, env_search(state->env, "PATH"), cmd->argv[0]); + if (param.exec_path == NULL) return (-1); - if (child_pid == 0) + if (cmd->in != NULL && (fd_in = open(cmd->in, O_RDONLY)) == -1) + return (-1); + if (cmd->out != NULL && (fd_out = open(cmd->out, + (cmd->is_append ? O_APPEND : O_RDONLY) | O_CREAT)) == -1) + return (-1); + param.argv = cmd->argv; + param.envp = (char**)state->env->data; + return (fork_wrap(fd_in, fd_out, ¶m, &execve_wrapper)); +} + +/* +** \brief Evaluate a line +** \param state State of the evaluation +** \param line Line to evaluate +** \return Last Executed command status or -1 on error +*/ +static int eval_line(void *param) +{ + int status; + t_eval_state *state; + t_line *line; + int fd_in; + int fd_out; + + state = ((t_fork_param_line*)param)->state; + line = ((t_fork_param_line*)param)->line; + fd_in = ((t_fork_param_line*)param)->fd_in; + fd_out = ((t_fork_param_line*)param)->fd_out; + + /* if (line->right == NULL) */ + /* return (eval(state, line->left)); */ + + /* if (line->sep == SEP_PIPE) */ + /* pipe(state->p); */ + + if (line->left->tag == TAG_LINE) { - pipe_setup_child(state->pipe_in, state->pipe_out); - if (is_builtin) - exit(builtin_dispatch_run(cmd->argv, state->env)); - else if (execve(exec_path, cmd->argv, NULL) == -1) - exit(EXIT_FAILURE); - exit(EXIT_SUCCESS); + return (fork_wrap(fd_in, fd_out, param, &eval_line)); } - wait(&child_pid); - return (WEXITSTATUS(child_pid)); + if ((status = eval(fd_in, fd_out, state, line->left)) == -1) + return (-1); + if ((line->sep == SEP_AND && status != 0) || + (line->sep == SEP_OR && status == 0)) + return (status); + + return (eval(fd_in, fd_out, state, line->right)); } /* ** \brief Evaluate an AST ** \param state State of the evaluation ** \param ast Abstract syntax tree to evaluate -** \return Executable status or -1 on error +** \return Last command status or -1 on error */ -int eval(t_eval_state *state, t_ast *ast) +int eval(int fd_in, int fd_out, t_eval_state *state, t_ast *ast) { + t_fork_param_line param; + errno = 0; if (ast->tag == TAG_LINE) - return (eval_line(state, &ast->data.line)); + { + param.state = state; + param.line = &ast->line; + param.fd_in = fd_in; + param.fd_out = fd_out; + return (eval_line(¶m)); + } if (ast->tag == TAG_CMD) - return (eval_cmd(state, &ast->data.cmd)); + return (eval_cmd(fd_in, fd_out, state, &ast->cmd)); return (-1); } diff --git a/src/glob.c b/src/glob.c new file mode 100644 index 0000000..2d544da --- /dev/null +++ b/src/glob.c @@ -0,0 +1,162 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* glob.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: charles <charles.cabergs@gmail.com> +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2020/04/05 11:44:07 by charles #+# #+# */ +/* Updated: 2020/04/05 13:21:25 by charles ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "ms_glob.h" + +/* +** \brief Match vector start size +** \note From ~: average file in directory is 8 +** From /: average file in directory is 15 +*/ + +#define MATCHES_VEC_START_SIZE 16 + +/* +** \brief Glob directory iteration function +** for subdirectory matches +** \param dirname Current directory name +** \param entry Current directory entry +** \param param Contain matches vector and pattern to match +** \param subdir_pattern Pattern left after '/' in parrent pattern +** \return 0 on success, -1 on error +*/ + +static int glob_iter_subdir( + char *dirname, + struct dirent *entry, + struct s_glob_param *param, + char *subdir_pattern +) +{ + char subdir_name[PATH_MAX]; + t_ftvec *subdir_matches; + size_t i; + + ft_strcat3(ft_strcpy(subdir_name, dirname), "/", entry->d_name); + chdir(subdir_name); + subdir_matches = glob_matches(subdir_pattern); + chdir(dirname); + if (subdir_matches == NULL) + return (-1); + i = 0; + while (i < subdir_matches->size) + if (ft_vecpush_safe(param->matches, ft_strjoin3(entry->d_name, + "/", subdir_matches->data[i++])) == NULL) + { + ft_vecdestroy(subdir_matches, free); + return (-1); + } + ft_vecdestroy(subdir_matches, free); + subdir_pattern[-1] = '/'; + return (0); +} + +/* +** \brief Glob directory iteration function +** \param dirname Current directory name +** \param entry Current directory entry +** \param param Contain matches vector and pattern to match +** \return 0 on success or -1 on error +*/ + +static int glob_iter( + char *dirname, + struct dirent *entry, + struct s_glob_param *param +) +{ + char *subdir_pattern; + + if (param->pattern[0] != '.' && entry->d_name[0] == '.') + return (0); + if ((subdir_pattern = ft_strchr(param->pattern, '/')) != NULL) + *subdir_pattern++ = '\0'; + if (!ft_fnmatch(param->pattern, entry->d_name)) + { + if (subdir_pattern != NULL) + subdir_pattern[-1] = '/'; + return (0); + } + if (subdir_pattern != NULL) + { + if (entry->d_type != DT_DIR) + { + subdir_pattern[-1] = '/'; + return (0); + } + return (glob_iter_subdir(dirname, entry, param, subdir_pattern)); + } + if (ft_vecpush_safe(param->matches, ft_strdup(entry->d_name)) == NULL) + return (-1); + return (0); +} + +/* +** \brief Fill a vector with all match +** \param pattern Pattern to match +** \return Matches vector or NULL on error +*/ + +t_ftvec *glob_matches(char *pattern) +{ + char dirname[PATH_MAX]; + struct s_glob_param param; + + if (getcwd(dirname, PATH_MAX) == NULL) + return (NULL); + if ((param.pattern = ft_strdup(pattern)) == NULL || + (param.matches = ft_vecnew(MATCHES_VEC_START_SIZE)) == NULL) + { + free(param.pattern); + return (NULL); + } + if (utils_directory_iter(dirname, ¶m, + (t_directory_iter_func)glob_iter) == -1) + { + free(param.pattern); + ft_vecdestroy(param.matches, free); + return (NULL); + } + free(param.pattern); + return (param.matches); +} + +/* +** \brief Search files which match a pattern in the current directory +** \param pattern Pattern to match +** \return Space separated list of match, +** pattern if no match found, +** NULL on error +*/ + +char *ms_glob(char *pattern) +{ + char *join; + t_ftvec *matches; + + if ((matches = glob_matches(pattern)) == NULL) + return (NULL); + ft_vecsort(matches, ft_compar_str); + if (ft_vecpush(matches, NULL) == NULL || + (join = ft_strsjoin((char**)matches->data, "\n")) == NULL) + { + ft_vecdestroy(matches, free); + return (NULL); + } + ft_vecdestroy(matches, free); + if (*join == '\0') + { + free(join); + return (ft_strdup(pattern)); + } + return (join); +} @@ -6,7 +6,7 @@ /* By: cacharle <marvin@42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/02/28 11:45:44 by cacharle #+# #+# */ -/* Updated: 2020/04/01 23:12:51 by charles ### ########.fr */ +/* Updated: 2020/04/05 12:15:57 by charles ### ########.fr */ /* */ /* ************************************************************************** */ @@ -18,6 +18,7 @@ #include "minishell.h" #include "ast.h" #include "eval.h" +#include "ms_glob.h" /* ** \brief Program entrypoint @@ -32,28 +33,28 @@ int main(int argc, char **argv, char **envp) (void)argc; (void)argv; /* (void)envp; */ - t_path path; + /* t_path path; */ t_env env; /* char *line; */ /* int ret; */ env = env_from_array(envp); - path = path_update(NULL, env_search(env, "PATH")); - - t_ast *ast; - t_line line; - t_cmd cmd; - t_eval_state state; - - cmd.argv = ft_split("ls -l", ' '); - cmd.in = NULL; - cmd.out = NULL; - cmd.is_append = false; - - line.left |
