aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--README.md4
-rw-r--r--include/ast.h17
-rw-r--r--include/eval.h22
-rw-r--r--include/minishell.h8
-rw-r--r--include/ms_glob.h32
-rw-r--r--include/utils.h31
m---------libft0
-rw-r--r--src/ast.c16
-rw-r--r--src/builtin/cd.c11
-rw-r--r--src/builtin/echo.c6
-rw-r--r--src/builtin/export.c6
-rw-r--r--src/builtin/unset.c5
-rw-r--r--src/env.c41
-rw-r--r--src/eval/eval.c148
-rw-r--r--src/glob.c162
-rw-r--r--src/main.c64
-rw-r--r--src/path.c28
-rw-r--r--src/preprocess.c69
-rw-r--r--src/utils.c54
20 files changed, 577 insertions, 149 deletions
diff --git a/Makefile b/Makefile
index 9ea9988..f3bfbd5 100644
--- a/Makefile
+++ b/Makefile
@@ -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 #
# #
# **************************************************************************** #
diff --git a/README.md b/README.md
index 4ab2ad4..7a82c5d 100644
--- a/README.md
+++ b/README.md
@@ -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
diff --git a/src/ast.c b/src/ast.c
index 2393a95..4c66fa7 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -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);
}
diff --git a/src/env.c b/src/env.c
index 66b4994..41aca6d 100644
--- a/src/env.c
+++ b/src/env.c
@@ -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, &param, &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(&param));
+ }
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, &param,
+ (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);
+}
diff --git a/src/main.c b/src/main.c
index c46324f..d9302ad 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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 = ast_new(TAG_CMD, &cmd);
- line.right = NULL;
- line.sep = SEP_END;
- ast = ast_new(TAG_LINE, &line);
+ /* 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 = ast_new(TAG_CMD, &cmd); */
+ /* line.right = NULL; */
+ /* line.sep = SEP_END; */
+ /* ast = ast_new(TAG_LINE, &line); */
/* printf("%p\n", ast); */
/* printf("%d\n", ast->tag); */
@@ -64,15 +65,20 @@ int main(int argc, char **argv, char **envp)
/* printf("%s\n", ast->data.line.left->data.cmd.argv[0]); */
/* printf("%s\n", ast->data.line.left->data.cmd.argv[1]); */
- state.pipe_in[0] = -1;
- state.pipe_in[1] = -1;
- state.pipe_out[0] = -1;
- state.pipe_out[1] = -1;
- state.path = path;
- state.env = env;
- printf("ret: %d %s\n", eval(&state, ast), strerror(errno));
+ /* state.pipe_in[0] = -1; */
+ /* state.pipe_in[1] = -1; */
+ /* state.pipe_out[0] = -1; */
+ /* state.pipe_out[1] = -1; */
+ /* state.path = path; */
+ /* sta