I am building a program that behaves like bash while handling pipes, redirections, heredocs, etc.
I have an issue with my code, which is: Every time I run a command like cat << a | sort < a.txt, my heredoc does this:
minishell> cat << a | sort < a.txt
heredoc> this is also in a.txt
this is in a.txt
heredoc> a
minishell>
I feel like there is some problem with my code timeline or something like this, but I can't figure out why. Here are some relevant parts of the code:
void ft_executer(t_minishell *ms)
{
int i;
t_cmd *curr;
i = 0;
curr = ms->cmd_lst;
ms->n_pipes = ft_count_pipes(ms->cmd_lst);
if (ms->n_pipes == 0)
ft_execute_only_cmd(ms, curr, curr->cmd);
else
{
ft_set_cmd_index(ms);
ft_open_pipes(ms);
while (curr)
{
ft_execute_mult_cmd(ms, curr, curr->cmd);
curr = curr->next;
}
ft_close_pipes(ms);
while (i < ms->n_pipes + 1)
waitpid(ms->pid[i++], NULL, 0);
}
}
void ft_execute_mult_cmd(t_minishell *ms, t_cmd *curr, char *cmd)
{
if (curr->heredoc[0])
waitpid(ms->pid_heredoc, NULL, 0);
ms->pid[curr->index] = fork();
if (ms->pid[curr->index] < 0)
ft_perror(ms, E_FORK, YES);
else if (ms->pid[curr->index] == 0)
{
if (ft_cmd_has_redir(curr) == YES)
ft_handle_redir(ms, curr);
ft_handle_pipes(ms, curr);
ft_close_pipes(ms);
ft_close_fds(curr);
ft_execute_cmd(ms, curr, cmd);
}
}
void ft_handle_pipes(t_minishell *ms, t_cmd *curr)
{
if (curr->index == 0)
{
dup2(curr->fd_in, STDIN_FILENO);
dup2(ms->pipe_fd[curr->index][1], STDOUT_FILENO);
}
else if (curr->next == NULL || curr->fd_out > STDOUT_FILENO)
{
dup2(ms->pipe_fd[curr->index - 1][0], STDIN_FILENO);
dup2(curr->fd_out, STDOUT_FILENO);
}
else
{
dup2(ms->pipe_fd[curr->index - 1][0], STDIN_FILENO);
dup2(ms->pipe_fd[curr->index][1], STDOUT_FILENO);
}
if (curr->fd_in > STDIN_FILENO)
dup2(curr->fd_in, STDIN_FILENO);
if (curr->fd_out > STDOUT_FILENO)
dup2(curr->fd_out, STDOUT_FILENO);
}
void ft_handle_redir(t_minishell *ms, t_cmd *curr)
{
int i;
i = 0;
while (curr->file_in[i])
curr->fd_in = ft_perror_fd(ms, curr->file_in[i++], T_FILE_IN);
i = 0;
while (curr->file_tr[i])
curr->fd_out = ft_perror_fd(ms, curr->file_tr[i++], T_FILE_TRUNC);
i = 0;
while (curr->file_ap[i])
curr->fd_out = ft_perror_fd(ms, curr->file_ap[i++], T_FILE_APPEND);
i = 0;
while (curr->heredoc[i])
curr->fd_in = ft_handle_heredoc(ms, curr->heredoc[i++]);
dup2(curr->fd_in, STDIN_FILENO);
dup2(curr->fd_out, STDOUT_FILENO);
}
int ft_perror_fd(t_minishell *ms, char *filename, t_type file_type)
{
int fd;
fd = 0;
if (file_type == T_FILE_IN)
fd = open(filename, O_RDONLY);
else if (file_type == T_FILE_TRUNC)
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
else if (file_type == T_FILE_APPEND)
fd = open(filename, O_WRONLY | O_CREAT | O_APPEND, 0644);
if (fd < 0)
ft_perror(ms, E_FILE, YES);
return (fd);
}
int ft_handle_heredoc(t_minishell *ms, char *delimiter)
{
ms->pid_heredoc = fork();
if (ms->pid_heredoc < 0)
ft_perror(ms, E_FORK, YES);
else if (ms->pid_heredoc == 0)
ft_create_heredoc(ms, delimiter);
else
waitpid(ms->pid_heredoc, NULL, 0);
return (open(".heredoc", O_RDONLY));
}
void ft_create_heredoc(t_minishell *ms, char *delimiter)
{
int fd;
char *line;
fd = open(".heredoc", O_WRONLY | O_CREAT | O_TRUNC, 0644);
while (42)
{
line = readline("heredoc> ");
if (!line)
{
ft_perror(ms, E_HEREDOC, YES);
break ;
}
if (line && ft_strncmp(line, delimiter, ft_strlen(line) + 1) == 0)
{
free(line);
break ;
}
line = ft_expand_heredoc(ms, line);
ft_putendl_fd(line, fd);
free(line);
}
close(fd);
if (ms->n_pipes > 0)
ft_free_pipes(ms);
ft_free_all(ms, YES);
}