/* ************************************************************************** */
/*                                                                            */
/*                                                        :::      ::::::::   */
/*   redirections.c                                     :+:      :+:    :+:   */
/*                                                    +:+ +:+         +:+     */
/*   By: sede-san <sede-san@student.42madrid.com    +#+  +:+       +#+        */
/*                                                +#+#+#+#+#+   +#+           */
/*   Created: 2026/02/12 00:00:00 by sede-san          #+#    #+#             */
/*   Updated: 2026/02/12 00:00:00 by sede-san         ###   ########.fr       */
/*                                                                            */
/* ************************************************************************** */

#include "executor.h"
#include <errno.h>

static int	open_redirection_target(
	const t_redirection *redirection
)
{
	if (redirection->type == TOKEN_REDIRECT_IN)
		return (open(redirection->target, O_RDONLY));
	if (redirection->type == TOKEN_REDIRECT_OUT)
		return (open(redirection->target, O_WRONLY | O_CREAT | O_TRUNC, 0644));
	if (redirection->type == TOKEN_APPEND)
		return (open(redirection->target, O_WRONLY | O_CREAT | O_APPEND, 0644));
	errno = EINVAL;
	return (-1);
}

static bool	backup_stream_if_needed(
	const t_redirection *redirection,
	int *saved_stdin,
	int *saved_stdout
)
{
	if (redirection->type == TOKEN_REDIRECT_IN && saved_stdin != NULL
		&& *saved_stdin == -1)
	{
		*saved_stdin = dup(STDIN_FILENO);
		if (*saved_stdin == -1)
			return (perror("dup"), false);
	}
	if ((redirection->type == TOKEN_REDIRECT_OUT
			|| redirection->type == TOKEN_APPEND) && saved_stdout != NULL
		&& *saved_stdout == -1)
	{
		*saved_stdout = dup(STDOUT_FILENO);
		if (*saved_stdout == -1)
			return (perror("dup"), false);
	}
	return (true);
}

bool	executor_apply_redirections(
	const t_command *command,
	int *saved_stdin,
	int *saved_stdout
)
{
	t_list			*node;
	t_redirection	*redirection;
	int				fd;

	if (saved_stdin != NULL)
		*saved_stdin = -1;
	if (saved_stdout != NULL)
		*saved_stdout = -1;
	if (command == NULL || command->redirections == NULL)
		return (true);
	node = command->redirections;
	while (node != NULL)
	{
		redirection = (t_redirection *)node->content;
		if (redirection == NULL || redirection->target == NULL)
			return (false);
		if (!backup_stream_if_needed(redirection, saved_stdin, saved_stdout))
			return (false);
		fd = open_redirection_target(redirection);
		if (fd == -1)
			return (perror(redirection->target), false);
		if (redirection->type == TOKEN_REDIRECT_IN
			&& dup2(fd, STDIN_FILENO) == -1)
			return (close(fd), perror("dup2"), false);
		if ((redirection->type == TOKEN_REDIRECT_OUT
				|| redirection->type == TOKEN_APPEND)
			&& dup2(fd, STDOUT_FILENO) == -1)
			return (close(fd), perror("dup2"), false);
		close(fd);
		node = node->next;
	}
	return (true);
}

void	executor_restore_redirections(
	int saved_stdin,
	int saved_stdout
)
{
	if (saved_stdin != -1)
	{
		if (dup2(saved_stdin, STDIN_FILENO) == -1)
			perror("dup2");
		close(saved_stdin);
	}
	if (saved_stdout != -1)
	{
		if (dup2(saved_stdout, STDOUT_FILENO) == -1)
			perror("dup2");
		close(saved_stdout);
	}
}
