You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言execve管道实现问题:输出被readline误解析致崩溃

管道命令输出被readline误解析问题

实现基于execve的管道处理逻辑时,已将带管道符|的命令拆分后逐个传入处理函数,通过fork、dup2和close完成管道搭建,命令整体可正常执行,但最后一条命令的输出会同时发送到终端和readline函数,导致readline将该输出当作用户输入的命令进行解析。例如执行ls | wc时,输出结果“8”被readline识别为命令,触发“8不是命令”的错误提示,甚至引发段错误。


主循环代码

while (++i < nproc)
{
    rdl->main_str = ft_strdup(rdl->pipe_str[i]);
    rdl->len = ft_strlen(rdl->pipe_str[i]);
    parser(rdl);
    command(rdl); // => run a pipe_exec function
    token_clear(&rdl->token);
    free(rdl->main_str);
    printf("*****************\n");
}
while (nproc-- > 0)
    waitpid(-1, 0, 0);

pipe_exec相关代码

#define READ 0
#define WRITE 1

static void ft_fatality(void)
{
    ft_putstr_fd("error: fatal\n", 2);
    exit(1);
}

// static void  ft_exec_error(char *str)
// {
//  ft_putstr_fd("error: cannot execute ", 2);
//  ft_putstr_fd(str, 2);
//  ft_putstr_fd("\n", 2);
//  exit(1);
// }

static void ft_openpipes(int fd[2])
{
    if (close(fd[READ]) == -1)
        ft_fatality();
    if (dup2(fd[WRITE], STDOUT_FILENO) == -1)
        ft_fatality();
    if (close(fd[WRITE]) == -1)
        ft_fatality();
}

static void ft_closepipes(int fd[2])
{
    if (dup2(fd[READ], STDIN_FILENO) == -1)
        ft_fatality();
    if (close(fd[READ]) == -1)
        ft_fatality();
    if (close(fd[WRITE]) == -1)
        ft_fatality();
}

int pipe_exec(t_command command)
{
    printf("pipe_exec\n");
    printf("pipe_exec command count %d\n", command.count);
    int i;
    int j;
    int fd[2];
    int type_size;
    int size;
    int result;
    char *arg;
    char *path;
    char **type;
    pid_t pid;

    i = -1;
    j = 1;
    result = 0;
    size = token_size(command.tokens);
    type_size = 0;
    arg = ft_strdup("");
    if (pipe(fd) == -1)
        ft_fatality();
    while (++i < size)
    {
        if (command.tokens->type_id == 12)
            type_size++;
        get_next_token(&command.tokens);
    }
    i = -1;
    path = command_find_path(command.keyword);
    type = (char **)malloc(sizeof(char *) * ((type_size + 1) + 2));
    type[0] = ft_strdup(path);
    while (++i < size)
    {
        if (command.tokens->type_id == 13 || command.tokens->type_id == 7)
        {
            arg = ft_strjoin(arg, command.tokens->context);
            printf("arg %s\n", arg);
        }
        if (command.tokens->type_id == 12 || size - 1 == command.tokens->id)
        {
            type[j++] = ft_strdup(arg);
            arg = ft_strdup("");
        }
        get_next_token(&command.tokens);
    }
    type[j] = NULL;
    j = -1;
    while (type[++j])
    {
        printf("type : %s\n", type[j]);
    }
    pid = fork();
    // signal(SIGINT, proc_signal_handler);
    if (pid < 0)
        return (-1);
    if (pid == 0)
    {
        ft_openpipes(fd);
        result = execve(path, type, g_env.env);
    }
    else
        ft_closepipes(fd);
    if (result == -1)
        return (1);
    waitpid(pid, 0, 0);
    command.fd[0] = fd[0];
    command.fd[1] = fd[1];
    free(arg);
    ft_free_dbl_str(type);
    free(path);
    return (0);
}

运行日志

bash % ./minishell
->ls | wc -l
-------------------
ls      token->type->context keyword                    token->type->id 0               token->t_flag 0
|       token->type->context pipe                       token->type->id 6               token->t_flag 6
wc      token->type->context keyword                    token->type->id 0               token->t_flag 0
l       token->type->context arg                        token->type->id 13              token->t_flag -1
-------------------
-------------------
ls      token->type->context keyword                    token->type->id 0               token->t_flag 0
-------------------
pipe_exec
pipe_exec command count 1
type : /bin/ls
*****************
-------------------
wc      token->type->context keyword                    token->type->id 0               token->t_flag 0
-       token->type->context option                     token->type->id 7               token->t_flag 5
l       token->type->context arg                        token->type->id 13              token->t_flag -1
-------------------
pipe_exec
pipe_exec command count 2
arg -
arg -l
type : /usr/bin/wc
type : -l
*****************
->       8
-------------------
8       token->type->context string                     token->type->id 12              token->t_flag -1
        token->type->context string                     token->type->id 12              token->t_flag -1
-------------------
**bash: 8: command not found
->zsh: segmentation fault  ./minishell**

内容的提问来源于stack exchange,提问作者Enes Özmert

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 03:31:37