aboutsummaryrefslogtreecommitdiff
path: root/src/eval
diff options
context:
space:
mode:
Diffstat (limited to 'src/eval')
-rw-r--r--src/eval/eval.c85
-rw-r--r--src/eval/exec.c62
-rw-r--r--src/eval/pipe.c48
3 files changed, 143 insertions, 52 deletions
diff --git a/src/eval/eval.c b/src/eval/eval.c
index 28cb386..d2fab39 100644
--- a/src/eval/eval.c
+++ b/src/eval/eval.c
@@ -5,89 +5,70 @@
#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
+*/
+
static int eval_line(t_eval_state *state, t_line *line)
{
int status;
if (line->right == NULL)
return (eval(state, line->left));
- status = eval(state, line->left);
+ if ((status = eval(state, line->left)) == -1)
+ return (-1);
if ((line->sep == SEP_AND && status != 0) ||
(line->sep == SEP_OR && status == 0))
return (status);
return (eval(state, line->right));
}
-static bool is_exec_path(char *path_str)
-{
- return (ft_strncmp(path_str, "../", 3) == 0
- || ft_strncmp(path_str, "./", 2) == 0
- || ft_strncmp(path_str, "/", 1) == 0);
-}
-
-static bool is_valid_exec(char *exec_path)
-{
- struct stat statbuf;
-
- if (stat(exec_path, &statbuf) != 0)
- return (false);
- if (!S_ISREG(statbuf.st_mode)) // also need to manage link
- return (false);
- // could test permission but probably handled by execve
- return (true);
-}
-
-static char *search_exec_path(t_path path, char *path_var, char *exec_name)
-{
- char *exec_path;
-
- if (is_exec_path(exec_name))
- return (exec_name);
- // try current first
- if ((exec_path = ft_htget(path, exec_name)) == NULL)
- {
- if (path_update(path, path_var) == NULL) // optimise by not updating not changed path in ht
- return (NULL);
- if ((exec_path = ft_htget(path, exec_name)) == NULL)
- return (NULL);
- }
- return (exec_path);
-}
+/**
+** \brief Evaluate a command
+** \param state Evaluation state
+** \param cmd Command to evaluate
+** \return Executable status or -1 on error
+*/
static int eval_cmd(t_eval_state *state, t_cmd *cmd)
{
int child_pid;
char *exec_path;
+ bool is_builtin;
- if ((exec_path = search_exec_path(state->path,
- ft_htget(state->env, "PATH"), cmd->argv[0])) == NULL)
- return (-1);
- if (cmd->in != NULL)
+ is_builtin = builtin_check_exec_name(cmd->argv[0]);
+ if (!is_builtin)
{
- if ((state->in_pipe[PIPE_WRITE] = open(cmd->in, O_RDONLY)) < 0)
- return (-1);
- }
- if (cmd->out != NULL)
- {
- if ((state->out_pipe[PIPE_READ] = open(cmd->out,
- (cmd->is_append ? O_WRONLY : O_APPEND) | O_CREAT)) < 0)
+ if ((exec_path = exec_search_path(state->path,
+ ft_htget(state->env, "PATH"), cmd->argv[0])) == NULL)
return (-1);
}
+ pipe_setup_parent(cmd, state->pipe_in, state->pipe_out);
if ((child_pid = fork()) == -1)
return (-1);
if (child_pid == 0)
{
- if (state->in_pipe[PIPE_READ] != PIPE_CLOSED)
- dup2(STDIN_FILENO, state->in_pipe[PIPE_READ]);
- if (state->out_pipe[PIPE_WRITE] != PIPE_CLOSED)
- dup2(STDOUT_FILENO, state->out_pipe[PIPE_WRITE]);
- if (execve(exec_path, cmd->argv, NULL /*env_array*/) == -1)
+ 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 /*env_array*/) == -1)
exit(EXIT_FAILURE);
+ exit(EXIT_SUCCESS);
}
wait(&child_pid);
return (WEXITSTATUS(child_pid));
}
+/**
+** \brief Evaluate an AST
+** \param state State of the evaluation
+** \param ast Abstract syntax tree to evaluate
+** \return Executable status or -1 on error
+*/
+
int eval(t_eval_state *state, t_ast *ast)
{
errno = 0;
diff --git a/src/eval/exec.c b/src/eval/exec.c
new file mode 100644
index 0000000..1ac9754
--- /dev/null
+++ b/src/eval/exec.c
@@ -0,0 +1,62 @@
+/**
+** \file exec.c
+** \brief Executable name and path
+*/
+
+#include "eval.h"
+
+/**
+** \brief Check if executable name is already a path
+** \param exec_name Executable name
+** \return True if valid
+*/
+
+bool exec_is_path(char *exec_name)
+{
+ return (ft_strncmp(exec_name, "../", 3) == 0
+ || ft_strncmp(exec_name, "./", 2) == 0
+ || ft_strncmp(exec_name, "/", 1) == 0);
+}
+
+/**
+** \brief Check if executable path is valid
+** \param exec_path Executable path
+** \return True if valid
+*/
+
+bool exec_is_valid(char *exec_path)
+{
+ struct stat statbuf;
+
+ if (stat(exec_path, &statbuf) != 0)
+ return (false);
+ if (!S_ISREG(statbuf.st_mode)) // also need to manage link
+ return (false);
+ // could test permission but probably handled by execve
+ return (true);
+}
+
+/**
+** \brief Search executable name in path
+** \param path Path hash table
+** \param path_var Path environment string in case we need to update path
+** \param exec_name Executable name to search
+** \return Executable path or NULL if not found or path update error
+*/
+
+char *exec_search_path(t_path path, char *path_var, char *exec_name)
+{
+ char *exec_path;
+
+ if (exec_is_path(exec_name))
+ return (exec_name);
+ // try current first
+ if ((exec_path = ft_htget(path, exec_name)) == NULL)
+ {
+ if (path_update(path, path_var) == NULL) // optimise by not updating not changed path in ht
+ return (NULL);
+ if ((exec_path = ft_htget(path, exec_name)) == NULL)
+ return (NULL);
+ }
+ return (exec_path);
+}
diff --git a/src/eval/pipe.c b/src/eval/pipe.c
new file mode 100644
index 0000000..897a5f2
--- /dev/null
+++ b/src/eval/pipe.c
@@ -0,0 +1,48 @@
+/**
+** \file pipe.c
+** \brief Pipes setup
+*/
+
+#include "eval.h"
+
+/**
+** \brief Setup STDIN and STDOUT pipe in the parent process
+** \param cmd Command to setup
+** \param pipe_in STDIN pipe
+** \param pipe_out STDOUT pipe
+** \return -1 on error, 0 otherwise
+*/
+
+int pipe_setup_parent(t_cmd *cmd, int pipe_in[2], int pipe_out[2])
+{
+ if (cmd->in != NULL)
+ {
+ if ((pipe_in[PIPE_WRITE] = open(cmd->in, O_RDONLY)) < 0)
+ return (-1);
+ }
+ if (cmd->out != NULL)
+ {
+ if ((pipe_out[PIPE_READ] = open(cmd->out,
+ (cmd->is_append ? O_WRONLY : O_APPEND) | O_CREAT)) < 0)
+ return (-1);
+ }
+ return (0);
+}
+
+/**
+** \brief Setup STDIN and STDOUT pipe in the child process
+** \param pipe_in STDIN pipe
+** \param pipe_out STDOUT pipe
+** \return -1 on error, 0 otherwise
+*/
+
+int pipe_setup_child(int pipe_in[2], int pipe_out[2])
+{
+ if (pipe_in[PIPE_READ] != PIPE_CLOSED)
+ if (dup2(STDIN_FILENO, pipe_in[PIPE_READ]) == -1)
+ return (-1);
+ if (pipe_out[PIPE_WRITE] != PIPE_CLOSED)
+ if (dup2(STDOUT_FILENO, pipe_out[PIPE_WRITE]) == -1)
+ return (-1);
+ return (0);
+}