/* ************************************************************************** */
/*                                                                            */
/*                                                        :::      ::::::::   */
/*   execution.c                                        :+:      :+:    :+:   */
/*                                                    +:+ +:+         +:+     */
/*   By: cchauvet <cchauvet@student.42angoulem      +#+  +:+       +#+        */
/*                                                +#+#+#+#+#+   +#+           */
/*   Created: 2023/02/21 12:45:16 by cchauvet          #+#    #+#             */
/*   Updated: 2023/02/28 14:56:05 by erey-bet         ###   ########.fr       */
/*                                                                            */
/* ************************************************************************** */

#include "execution_private.h"

static int	ft_own_cmd(t_data *data, t_cmd *cmd)
{
	int	return_code;

	return_code = -1;
	if (ft_strcmp(cmd->executable, "pwd") == 0)
		return_code = pwd(cmd->fd_out[0]);
	else if (ft_strcmp(cmd->executable, "env") == 0)
		return_code = print_env(data->env, cmd->fd_out[0]);
	else if (ft_strcmp(cmd->executable, "export") == 0)
		return_code = (ft_export(data->env,cmd->args + 1, cmd->fd_out[0]));
	else if (ft_strcmp(cmd->executable, "cd") == 0)
		return_code = (move_folder(cmd->args + 1, cmd->fd_out[0]));
	else if (ft_strcmp(cmd->executable, "unset") == 0)
		return_code = (unset(data->env, cmd->args, cmd->fd_out[0]));
	else if (ft_strcmp(cmd->executable, "echo") == 0)
		return_code = (echo(cmd->fd_out[0], cmd->args + 1));
	else if (ft_strcmp(cmd->executable, "exit") == 0)
	{
		return_code = ft_exit(cmd->args + 1);
		if (return_code >= 0)
		{
			data->exit_code = return_code;
			return (-1);
		}
	}
	data->exit_code = return_code;
	return (return_code);
}

static bool	ft_executor(t_cmd *cmd, char **env, int fd)
{
	if (cmd->fd_in[0] == -1 || cmd->fd_out[0] == -1 || cmd->executable == NULL)
		return (0);
	cmd->pid = fork();
	ft_get_data()->child_pid = cmd->pid;
	if (cmd->pid == -1)
		return (1);
	if (cmd->pid == 0)
	{
		dup2(cmd->fd_in[0], 0);
		dup2(cmd->fd_out[0], 1);
		if (fd != -1)
			close(fd);
		ft_closer(cmd->fd_in);
		ft_closer(cmd->fd_out);
		execve(cmd->executable, cmd->args, env);
		ft_eprintf("minishell: permission denied: %s\n", cmd->executable);
		return (1);
	}
	return (0);
}

static int	ft_cmd_executor(t_data *data, t_cmd *cmd, int fd)
{
	int		exit_code;
	char	**env;

	if (cmd->own_cmd == 1)
	{
		exit_code = ft_own_cmd(data, cmd);
		ft_closer(cmd->fd_in);
		ft_closer(cmd->fd_out);
		if (exit_code == -1)
			return (1);
	}
	else
	{
		env = env_to_strs(data->env);
		if (env == NULL)
			return (1);
		exit_code = ft_executor(cmd, env, fd);
		ft_closer(cmd->fd_in);
		ft_closer(cmd->fd_out);
		ft_freer_tab_ultimate(1, env);
		if (exit_code == 1)
			return (1);
	}
	return (0);
}

int	ft_cmds_executor(t_data *data)
{
	int		fds[2];
	t_list	*current;
	t_cmd	*content;

	current = *data->cmds;
	while (current != NULL)
	{
		content = current->content;
		fds[0] = -1;
		fds[1] = -1;
		if (current->next != NULL)
		{
			if (pipe(fds) == -1)
				return (1);
			ft_add_fd(content->fd_out, fds[1]);
			ft_add_fd(((t_cmd *) (current->next->content))->fd_in, fds[0]);
		}
		if (ft_cmd_executor(data, content, fds[0]))
			return (1);
		current = current->next;
	}
	return (0);
}
