为什么管道对cat | cat | ls不起作用?

huangapple go评论69阅读模式
英文:

Why pipes not working for cat | cat | ls?

问题

以下是代码部分的翻译:

void	executing_commands(t_minish *data)
{
    t_cmd	*cmd;
    int process_status;

    process_status = 0;
    cmd = data->cmds;
    if (!cmd->full_cmd)
        return ;
    creating_pipes(data);
    while (cmd && cmd->full_cmd)
        cmd = creating_child(&cmd, data);
    closing_all_fd(data);
    cmd = data->cmds;
    while (cmd)
    {
        waitpid(data->child, &process_status, 0);
        if (data->cmds && !check_parent_builtin(&cmd))
            g_status = WEXITSTATUS(process_status);
        cmd = cmd->next;
    }
}

t_cmd	*creating_child(t_cmd **cmd, t_minish *data)
{
    int	pid;

    if (check_parent_builtin(cmd))
        executing_builtin(data, cmd);
    else
    {
        pid = fork();
        if (ft_memcmp((*cmd)->full_cmd[0], "minishell", 10))
            set_signals(EXEC);
        data->child = pid;
        if (pid == -1)
        {
            closing_all_fd(data);
            error_manager(2, data, NULL);
        }
        else if (pid == 0)
            child_process(data, cmd);
    }
    return (*cmd)->next;
}

void	child_process(t_minish *data, t_cmd **cmd)
{
    switching_input_output(data, cmd);
    closing_all_fd(data);
    if (check_child_builtin(cmd))
        executing_builtin(data, cmd);
    else
        launching_command(data, cmd);
}

void	switching_input_output(t_minish *data, t_cmd **cmd)
{
    if ((*cmd)->output > 1)
    {
        if (dup2((*cmd)->output, STDOUT_FILENO) < 0)
            error_manager(6, data, cmd);
        close((*cmd)->output);
    }
    if ((*cmd)->input)
    {
        if (dup2((*cmd)->input, STDIN_FILENO) < 0)
            error_manager(6, data, cmd);
        close((*cmd)->input);
    }
    if ((*cmd)->file_in)
    {
        if (dup2((*cmd)->file_in, STDIN_FILENO) < 0)
            error_manager(6, data, cmd);
        close((*cmd)->file_in);
    }
    if ((*cmd)->file_out)
    {
        if (dup2((*cmd)->file_out, STDOUT_FILENO) < 0)
            error_manager(6, data, cmd);
        close((*cmd)->file_out);
    }
}

void	launching_command(t_minish *data, t_cmd **cmd)
{
    if (execve((*cmd)->full_path, (*cmd)->full_cmd, data->env_table) == -1)
        error_manager(3, data, cmd);
}

void	closing_all_fd(t_minish *data)
{
    t_cmd	*cmd;

    cmd = data->cmds;
    while (cmd)
    {
        if (cmd->input)
            close(cmd->input);
        if (cmd->output > 1)
            close(cmd->output);
        cmd = cmd->next;
    }
}

void	closing_fd_if_redirections(t_minish *data)
{
    t_cmd	*cmd;

    cmd = data->cmds;
    while (cmd)
    {
        if (cmd->file_in && cmd->input)
            close(cmd->input);
        cmd = cmd->next;
    }
}

void	creating_pipes(t_minish *data)
{
    int		fd[2];
    t_cmd	*cmd;

    cmd = data->cmds;
    while (cmd->next != NULL)
    {
        if (pipe(fd) == -1)
            error_manager(1, data, NULL);
        cmd->output = fd[1];
        cmd->next->input = fd[0];
        if (!cmd->next->next)
            cmd->next->last = 1;
        cmd = cmd->next;
    }
    closing_fd_if_redirections(data);
}

如果您需要更多帮助或有其他问题,请随时提出。

英文:

I really need help and any suggestions will be very welcomed. Me and a mate have coded a mini version of the Shell and I did parsing and executing parts. All is working properly except for some cases that probably are hiding some logic that I can't catch and I'm actually stuck. In particular when launching cat | cat | ls cmd the ls output is ok but the cat behavior is not what expected. Instead of waiting for the stdin (not having any argument) the prompt is suddenly returned. That probably means that there's an issue with pipes not closing at the right place, but I'm not able to find where exactly. Here below you will find the executing part. If anyone please could help with kindness and a noncompetitive attitude will be very appreciated. Here is the github repo for any further details GitHub Repo

void	executing_commands(t_minish *data)
{
t_cmd	*cmd;
int process_status;
process_status = 0;
cmd = data-&gt;cmds;
if (!cmd-&gt;full_cmd)
return ;
creating_pipes(data);
while (cmd &amp;&amp; cmd-&gt;full_cmd)
cmd = creating_child(&amp;cmd, data);
closing_all_fd(data);
cmd = data-&gt;cmds;
while (cmd)
{
waitpid(data-&gt;child, &amp;process_status, 0);
if (data-&gt;cmds &amp;&amp; !check_parent_builtin(&amp;cmd))
g_status = WEXITSTATUS(process_status);
cmd = cmd-&gt;next;
}
}
t_cmd	*creating_child(t_cmd **cmd, t_minish *data)
{
int	pid;
if (check_parent_builtin(cmd))
executing_builtin(data, cmd);
else
{
pid = fork();
if (ft_memcmp((*cmd)-&gt;full_cmd[0], &quot;minishell&quot;, 10))
set_signals(EXEC);
data-&gt;child = pid;
if (pid == -1)
{
closing_all_fd(data);
error_manager(2, data, NULL);
}
else if (pid == 0)
child_process(data, cmd);
}
return ((*cmd)-&gt;next);
}
void	child_process(t_minish *data, t_cmd **cmd)
{
switching_input_output(data, cmd);
closing_all_fd(data);
if (check_child_builtin(cmd))
executing_builtin(data, cmd);
else
launching_command(data, cmd);
}
void	switching_input_output(t_minish *data, t_cmd **cmd)
{
if ((*cmd)-&gt;output &gt; 1)
{
if (dup2((*cmd)-&gt;output, STDOUT_FILENO) &lt; 0)
error_manager(6, data, cmd);
close((*cmd)-&gt;output);
}
if ((*cmd)-&gt;input)
{
if (dup2((*cmd)-&gt;input, STDIN_FILENO) &lt; 0)
error_manager(6, data, cmd);
close((*cmd)-&gt;input);
}
if ((*cmd)-&gt;file_in)
{
if (dup2((*cmd)-&gt;file_in, STDIN_FILENO) &lt; 0)
error_manager(6, data, cmd);
close((*cmd)-&gt;file_in);
}
if ((*cmd)-&gt;file_out)
{
if (dup2((*cmd)-&gt;file_out, STDOUT_FILENO) &lt; 0)
error_manager(6, data, cmd);
close((*cmd)-&gt;file_out);
}
}
void	launching_command(t_minish *data, t_cmd **cmd)
{
if (execve((*cmd)-&gt;full_path, (*cmd)-&gt;full_cmd, data-&gt;env_table) == -1)
error_manager(3, data, cmd);
}
void	closing_all_fd(t_minish *data)
{
t_cmd	*cmd;
cmd = data-&gt;cmds;
while (cmd)
{
if (cmd-&gt;input)
close(cmd-&gt;input);
if (cmd-&gt;output &gt; 1)
close(cmd-&gt;output);
cmd = cmd-&gt;next;
}
}
void	closing_fd_if_redirections(t_minish *data)
{
t_cmd	*cmd;
cmd = data-&gt;cmds;
while (cmd)
{
if (cmd-&gt;file_in &amp;&amp; cmd-&gt;input)
close(cmd-&gt;input);
cmd = cmd-&gt;next;
}
}
void	creating_pipes(t_minish *data)
{
int		fd[2];
t_cmd	*cmd;
cmd = data-&gt;cmds;
while (cmd-&gt;next != NULL)
{
if (pipe(fd) == -1)
error_manager(1, data, NULL);
cmd-&gt;output = fd[1];
cmd-&gt;next-&gt;input = fd[0];
if (!cmd-&gt;next-&gt;next)
cmd-&gt;next-&gt;last = 1;
cmd = cmd-&gt;next;
}
closing_fd_if_redirections(data);
}

I tried not to create all the pipes needed all in a sudden in order to better control closing in parent and child processes with just a pipe for each loop but still not working

答案1

得分: 1

>…提示突然返回。这可能意味着管道没有在正确位置关闭的问题…

你的概率估计出错了。错误在于shell不等待管道中所有的命令,因为尽管你在executing_commands函数中的while (cmd)循环中正确地尝试等待每个命令,但整个管道只有一个存储位置data->child,所以子进程PID会被后续的命令覆盖,最终shell只能等待最后一个命令。
当然,解决方法是将child按照cmd而不是data存储。

英文:

>… the prompt is suddenly returned. That probably means that there's an issue with pipes not closing at the right place …

Your probability estimation went wrong. The error is that the shell does not wait for all the commands in the pipeline, because, though you rightly try to wait for each command in the while (cmd) loop in executing_commands, there is only one storage location data-&gt;child for the whole pipeline, so a child PID is overwritten by the following, and at the end the shell can only wait for the last command.
Of course the remedy is to store child per cmd rather than per data.

huangapple
  • 本文由 发表于 2023年3月31日 16:34:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/75896444.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定