aboutsummaryrefslogtreecommitdiff
path: root/src/eval/eval.c
blob: d40c7f374260d014f26596f0ed4fba6c79801071 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
/**
** \file   eval.c
** \brief  Evaluation of an AST
*/

#include "eval.h"

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 ((line->sep == SEP_AND && status != 0) ||
		(line->sep == SEP_OR && status == 0))
		return (status);
	return (eval(state, line->right));
}

static char	*search_exec_path(t_path path, char *path_var, char *exec_name)
{
	char	*exec_path;

	// try current first
	if ((exec_path = ft_htget(path, exec_name)) == NULL)
	{
		if (path_update(path, path_var) == NULL)
			return (NULL);
		if ((exec_path = ft_htget(path, exec_name)) == NULL)
			return (NULL);
	}
	return exec_path;
}

static int eval_cmd(t_eval_state *state, t_cmd *cmd)
{
	int		child_pid;
	char	*exec_path;

	if ((exec_path = search_exec_path(state->path, ft_htget(state->env, "PATH"), cmd->argv[0])) == NULL)
		return (-1);
	if (cmd->in != NULL)
	{
		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)
			return (-1);
	}

	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)
			exit(EXIT_FAILURE);
	}
	wait(&child_pid);
	return (WEXITSTATUS(child_pid));
}

int	eval(t_eval_state *state, t_ast *ast)
{
	if (ast->tag == TAG_LINE)
		return eval_line(state, &ast->data.line);
	if (ast->tag == TAG_CMD)
		return eval_cmd(state, &ast->data.cmd);
	return (-1);
}